 /**
 * 逻辑、功能相关描述: <br>
 *
 * @author 付湘辉  <br>
 * 编写日期：2008-8-29  <br>
 */
package com.ce.pms.charge.service.impl;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.util.Assert;

import com.ce.pms.base.service.impl.PmsBaseServiceImpl;
import com.ce.pms.charge.dao.IBusinessCodeDao;
import com.ce.pms.charge.dao.IChargeStaDao;
import com.ce.pms.charge.dao.IChargeVoucherDao;
import com.ce.pms.charge.dao.ISubAccountDao;
import com.ce.pms.charge.dao.ITransactionDao;
import com.ce.pms.charge.model.AbstractStaVersion;
import com.ce.pms.charge.model.AbstractSubAccount;
import com.ce.pms.charge.model.AbstractTrans;
import com.ce.pms.charge.model.AccountDomain;
import com.ce.pms.charge.model.BusinessCodeDomain;
import com.ce.pms.charge.model.ChargeAccountDomain;
import com.ce.pms.charge.model.CreditTransDomain;
import com.ce.pms.charge.model.DebitTransDomain;
import com.ce.pms.charge.model.DepositAccountDO;
import com.ce.pms.charge.model.LatefeeDetail;
import com.ce.pms.charge.model.PeriodDomain;
import com.ce.pms.charge.model.PrePayAccountDomain;
import com.ce.pms.charge.model.TraRtra;
import com.ce.pms.charge.model.VoucherDomain;
import com.ce.pms.charge.service.IAccountService;
import com.ce.pms.charge.service.IPeriodService;
import com.ce.pms.charge.service.ISubAccountService;
import com.ce.pms.charge.service.ITransactionService;
import com.ce.pms.charge.vo.AbstractTransVO;
import com.ce.pms.charge.vo.AdjustTransactionVO;
import com.ce.pms.charge.vo.ChargeDetailSearchVO;
import com.ce.pms.charge.vo.CreditTransVO;
import com.ce.pms.charge.vo.DebitTransVO;
import com.ce.pms.charge.vo.DepositTransSearchVO;
import com.ce.pms.charge.vo.DepositTransVO;
import com.ce.pms.charge.vo.LateFeeDetailVO;
import com.ce.pms.charge.vo.PeriodVO;
import com.ce.pms.charge.vo.PrePaySchChargeVO;
import com.ce.pms.charge.vo.TransactionVO;
import com.ce.pms.common.model.SysInfo;
import com.ce.pms.common.model.SysrefcodeDO;
import com.ce.pms.common.service.ISecUserService;
import com.ce.pms.common.util.BigDecimalUtil;
import com.ce.pms.common.util.PmsUtilityComparator;
import com.ce.pms.exception.BusinessException;
import com.ce.pms.house.model.HouseDomain;
import com.ce.pms.house.service.IHouseService;
import com.ce.pms.house.vo.PrecinctVO;
import com.ce.util.BeanUtil;
import com.ce.util.BlankUtil;
import com.ce.util.DateUtil;
import com.sitechasia.webx.core.support.Page;

/**
 * 	名称: com.ce.pms.charge.service.impl.TransactionServiceImpl <br>
 *
 *
 * @author  付湘辉  <br>
 * Created on： 2008-8-29 <br>
 * @author <br>
 * update on： <br>
 * why: <br>
 */
public class TransactionServiceImpl extends PmsBaseServiceImpl implements
		ITransactionService {
	private static final String FROM_HOUSE_NUMBER="来源房号：";

	/**
	 * 交易备注字段长度，这个长度参考AbstractTrans.remark
	 */
	private static final int TRANS_REMARK_LENGTH = 500;

	/**
	 * 交易备注字段周期部分描述
	 */
	private static final String TRANS_REMARK_PERIOD = "周期做此操作, 其主交易为：";


	private IAccountService accountService;

	/**
	 * 交易码Dao
	 */
	private IBusinessCodeDao businessCodeDao;

	/**
	 * 收费标准dao
	 */
	private IChargeStaDao chargeStaDao;

	/**
	 * 收费凭证dao
	 */
	private IChargeVoucherDao chargeVoucherDao;

	/**
	 * 员工姓名缓冲，以用户id为key,员工姓名为value
	 */
	private Map<Long, String> hmployeeNameCacheMap;

	/**
	 * 房屋Service
	 */
	private IHouseService houseService;

	/**
	 * 收费周期
	 */
	private IPeriodService periodService;

	/**
	 * 用户Service
	 */
	private ISecUserService secUserService;

	/**
	 * 子帐户dao
	 */
	private ISubAccountDao subAccountDao;
	/**
	 * 子账户Service
	 */
	private ISubAccountService subAccountService;

	/**
	 * 交易dao
	 */
	private ITransactionDao transactionDao;

	private Map<String, String> transClazzMap;

	private Map<String, String> transStatusMap;

	/**
	 * 功能描述:　
	 * 　<ul><li>添加一笔调整交易 </li></ul>
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public AdjustTransactionVO addAdjustTransaction(AdjustTransactionVO adjustTransVO){
		super.checkParameterIsNull(adjustTransVO, "common:parameters_null_exception, ");
		//调整后不能为负数
		if (1 == BigDecimal.ZERO.compareTo(adjustTransVO.getReliefBalance())) {
			throw new BusinessException("charge:charge_relief_not_negative_exception",
										BusinessException.WARNING);
		}

		//交易类型是调整交易
		adjustTransVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_ADJUSTMENT);
		adjustTransVO.setInputDate(super.getDate());
		//在备注字段中加入衍生交易的交易摘要说明
		this.dealDerivativeTransRemark(adjustTransVO);

		//增加一笔应收交易
		this.addDebitTransAction(adjustTransVO);

		dealTransactionRelation(adjustTransVO.getPrincipalTrans(),adjustTransVO,SysrefcodeDO.FEE_TRA_R_TRA_RELATION_TYPE_ADJUSTMENT);
		return adjustTransVO;
	}

	/**
	 * 功能描述: 添加一笔物业账户收费交易 <br>
	 * @param creditTransVO 实收交易VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:付湘辉  <br>
	 * Edit on:2009-1-7    <br>
	 * Why: 建议调用：addChargeTransactionReality    <br>
	 */
	@Deprecated
	public CreditTransVO addChargeTransaction(CreditTransVO creditTransVO){
		super.checkParameterIsNull("common:parameters_null_exception, ",creditTransVO);
		super.checkParameterIsNull("common:parameters_null_exception, ",
									creditTransVO.getAccountId(),
									creditTransVO.getSubAccountId());
		super.checkCreatorInfo(creditTransVO.getCreator());

		if (BlankUtil.isBlank(creditTransVO.getDebits())) {
			throw new BusinessException("charge:charge_transaction_not_debittrans_exception",
					BusinessException.WARNING);
		}

		// 判断子账户贷方是否锁定
		Boolean isLock = this.subAccountService.isLockCredit(creditTransVO.getSubAccountId());
		if (isLock) {
			throw new BusinessException("charge:charge_account_credit_locked_exception",
										BusinessException.WARNING);
		}
		this.checkMultiplePayPrice(creditTransVO);

		//收费交易类型005
		creditTransVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_MAINPAY);
		//凭证号前缀JFT
		creditTransVO.setVoucherNoPrefix(SysrefcodeDO.CHARGE_VOUCHERNO_PREFIX);

		SysInfo sysInfo = null;
		if (!BlankUtil.isBlank(creditTransVO.getSysDate())) {
			sysInfo = new SysInfo();
			sysInfo.setCreator(creditTransVO.getCreator());
			sysInfo.setSysDate(creditTransVO.getSysDate());
		}else{
			sysInfo = super.createInfo(creditTransVO.getCreator());
			creditTransVO.setSysDate(sysInfo.getSysDate());
		}

		//生成凭证
		VoucherDomain voucher = this.createVoucher(creditTransVO, sysInfo);
		creditTransVO.setVoucherId(voucher.getVoucherId());

        //增加主支付交易
		creditTransVO = this.addCreditTransAction(creditTransVO, sysInfo);
		//处理一笔主支付交易的子支付交易(如果是多重支付生效)
		Set<CreditTransVO> sets = dealSubPayTrans(creditTransVO);

        //查询出主支付交易实体
		AbstractTrans mainPayTrans = this.transactionDao.findById(creditTransVO.getTransactionId());

        // 处理应收-实收关系
        this.dealDebitAndCreditRelation(creditTransVO, mainPayTrans);

		//处理多重支付时主支付与子支付关系
		this.dealMainPayAndSubForMultiple(sets, mainPayTrans);

		this.transactionDao.updateObject(mainPayTrans);

		return creditTransVO;
	}

	/**
	 * 功能描述: <ul><li>针对物业收费账户，添加一笔实际收费交易，
	 * 在参数creditTransVO中应该为accountHouseId属性赋值，
	 * accountHouseId属性是指账户所属房屋的ID,房屋可能是管理房或者产权房。 </li></ul>
	 * @param creditTransVO 实收交易VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public CreditTransVO addChargeTransactionReality(CreditTransVO creditTransVO){
		super.checkParameterIsNull(creditTransVO, "common:parameters_null_exception, ");
		super.checkParameterIsNull(creditTransVO.getAccountHouseId(), "common:parameters_null_exception, ");
		// 查找房间收费账户
		AccountDomain account = this.accountService.getCurrentAccount(creditTransVO.getAccountHouseId());
		creditTransVO.setAccountId(account.getAccountId());
		ChargeAccountDomain chargeAccount  = this.accountService.getChargeAccountByAccount(account);
		creditTransVO.setSubAccountId(chargeAccount.getSubAccountId());
		//查找当前收费周期
		PeriodVO periodVo = this.periodService.queryCurrentPeriod();
		creditTransVO.setPeriodId(periodVo.getKeyword());
		//查找所在收费管理区号
		PrecinctVO precinctVO  = this.houseService.getPrecinctVOByHouseId(creditTransVO.getAccountHouseId(), null);
		creditTransVO.setPrecinctCode(precinctVO.getPrecinctCode());
		return this.addChargeTransaction(creditTransVO);
	}

	/**
	 * 功能描述: <ul><li>添加一笔应收本金交易，
	 * 除必填项外，在参数debitTransVO中应该为accountHouseId属性赋值，
	 * accountHouseId属性是指账户所属房屋的ID,房屋可能是管理房或者产权房。 </li></ul>
	 * @param debitTransVO 应收交易VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public DebitTransVO addDebitPrincipalTransaction(DebitTransVO debitTransVO){
		super.checkParameterIsNull(debitTransVO, "common:parameters_null_exception, ");
		super.checkParameterIsNull(debitTransVO.getAccountHouseId(), "common:parameters_null_exception, ");
		//查找房间收费账户
		AccountDomain account = this.accountService.getCurrentAccount(debitTransVO.getAccountHouseId());
		ChargeAccountDomain chargeAccount  = this.accountService.getChargeAccountByAccount(account);
		debitTransVO.setSubAccountId(chargeAccount.getSubAccountId());
		//查找当前收费周期
		PeriodVO periodVo = this.periodService.queryCurrentPeriod();
		debitTransVO.setPeriodId(periodVo.getKeyword());
		debitTransVO.setPeriod(periodVo.getPeriod());
		return this.addPrincipalTransaction(debitTransVO);
	}

	/**
	 * 功能描述: <ul><li>针对同一个物业帐户，批量新增应收本金交易，
	 * accountHouseId属性是指账户所属房屋的ID,房屋可能是管理房或者产权房。 </li></ul>
	 * @param operator 操作者ID
	 * @param accountHouseId 账户所属房屋的ID
	 * @param debitTransVOs 应收交易VO集
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public List<DebitTransVO> addDebitPrincipalTransactionBatch(Long operator,Long accountHouseId,List<DebitTransVO> debitTransVOs){
		super.checkParameterIsNull("common:parameters_null_exception, ",operator,accountHouseId,debitTransVOs);
		//	查找房间收费账户
		AccountDomain account = this.accountService.getCurrentAccount(accountHouseId);
		ChargeAccountDomain chargeAccount  = this.accountService.getChargeAccountByAccount(account);
		final Long subAccountId = chargeAccount.getSubAccountId();
		//查找当前收费周期
		PeriodVO periodVo = this.periodService.queryCurrentPeriod();
		final Long periodId = periodVo.getKeyword();
		final String period = periodVo.getPeriod();
		for (Iterator<DebitTransVO> iter = debitTransVOs.iterator(); iter.hasNext();) {
			DebitTransVO debitVo =iter.next();
			debitVo.setPeriodId(periodId);
			debitVo.setPeriod(period);
			debitVo.setSubAccountId(subAccountId);
		}

		return this.addPrincipalTransactionBatch(operator, subAccountId, debitTransVOs);
	}

	/**
	 * 功能描述: <ul><li>针对押金(保证金)子账户，添加一笔押金收款交易，
	 * 在参数depositTransVO中应该为accountHouseId属性赋值，
	 * accountHouseId属性是指账户所属房屋的ID,房屋可能是管理房或者产权房。 </li></ul>
	 * @param depositTransVO 押金实收交易VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public DepositTransVO addDepositCharge(DepositTransVO depositTransVO){
		Assert.notNull(depositTransVO);
		Assert.notNull(depositTransVO.getAccountHouseId());
		Assert.notNull(depositTransVO.getBusinessId());
		checkCreatorInfo(depositTransVO.getCreator());
		checkCreditForPreDepCharge(depositTransVO);
		
		// 查找房间收费账户
		AccountDomain account = this.accountService.getCurrentAccount(depositTransVO.getAccountHouseId());
		depositTransVO.setAccountId(account.getAccountId());
		DepositAccountDO depositAccount  = this.accountService.getDepositAccountByAccount(account);
		// 判断子账户贷方是否锁定
		Boolean isLock = this.subAccountService.isLockCredit(depositAccount.getSubAccountId());
		if (isLock) {
			throw new BusinessException("charge:charge_account_credit_locked_exception",
										BusinessException.WARNING);
		}
		depositTransVO.setSubAccountId(depositAccount.getSubAccountId());
		//查找当前收费周期
		PeriodVO periodVo = this.periodService.queryCurrentPeriod();
		depositTransVO.setPeriodId(periodVo.getKeyword());
		//查找所在收费管理区号
		PrecinctVO precinctVO  = this.houseService.getPrecinctVOByHouseId(depositTransVO.getAccountHouseId(), null);
		depositTransVO.setPrecinctCode(precinctVO.getPrecinctCode());

		// 收款交易类型009
		depositTransVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_DEPOSIT_CHARGE);
		SysInfo sysInfo = null;
		if (!BlankUtil.isBlank(depositTransVO.getSysDate())) {
			sysInfo = new SysInfo();
			sysInfo.setCreator(depositTransVO.getCreator());
			sysInfo.setSysDate(depositTransVO.getSysDate());
		}else{
			sysInfo = super.createInfo(depositTransVO.getCreator());
			depositTransVO.setSysDate(sysInfo.getSysDate());
		}
		return this.addOneDepositTransVOInner(depositTransVO,sysInfo);
	}

	/**
	 * 功能描述: 针对预交款子账户，添加一笔预交款收款交易 <br>
	 * @param prePaySchChargeVO 预交款账户收款VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public PrePaySchChargeVO addPrePayChargeTransaction(PrePaySchChargeVO prePaySchChargeVO){
		super.checkParameterIsNull("common:parameters_null_exception, ",prePaySchChargeVO);
		super.checkParameterIsNull("common:parameters_null_exception, ",
				prePaySchChargeVO.getAccountHouseId());
		super.checkCreatorInfo(prePaySchChargeVO.getCreator());
		this.checkCreditForPreDepCharge(prePaySchChargeVO);

		if (BlankUtil.isBlank(prePaySchChargeVO.getAccountId())
				|| BlankUtil.isBlank(prePaySchChargeVO.getSubAccountId())) {
			// 查找房间收费账户
			AccountDomain account = this.accountService.getCurrentAccount(prePaySchChargeVO.getAccountHouseId());
			Long accountId = account.getAccountId();
			prePaySchChargeVO.setAccountId(accountId);
			PrePayAccountDomain  prePayAccount  = this.accountService.getPrePayAccountByAccount(account);
			Long subAccountId = prePayAccount.getSubAccountId();
			prePaySchChargeVO.setSubAccountId(subAccountId);
		}

		//判断子账户贷方是否锁定
		Boolean isLock = this.subAccountService.isLockCredit(prePaySchChargeVO.getSubAccountId());
		if (isLock) {
			throw new BusinessException("charge:charge_account_credit_locked_exception",
										BusinessException.WARNING);
		}
		if (BlankUtil.isBlank(prePaySchChargeVO.getPeriodId())) {
			// 查找当前收费周期
			PeriodVO periodVo = this.periodService.queryCurrentPeriod();
			prePaySchChargeVO.setPeriodId(periodVo.getKeyword());
		}
		if (BlankUtil.isBlank(prePaySchChargeVO.getPrecinctCode())) {
			// 查找所在收费管理区号
			PrecinctVO precinctVO  = this.houseService.getPrecinctVOByHouseId(prePaySchChargeVO.getAccountHouseId(), null);
			prePaySchChargeVO.setPrecinctCode(precinctVO.getPrecinctCode());
		}

		//收款交易类型007
		prePaySchChargeVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_PRERECEIVABLES);
		//凭证号前缀YJK
		prePaySchChargeVO.setVoucherNoPrefix(SysrefcodeDO.EINZUG_VOUCHERNO_PREFIX);
		SysInfo sysInfo = null;
		if (!BlankUtil.isBlank(prePaySchChargeVO.getSysDate())) {
			sysInfo = new SysInfo();
			sysInfo.setCreator(prePaySchChargeVO.getCreator());
			sysInfo.setSysDate(prePaySchChargeVO.getSysDate());
		}else{
			sysInfo = super.createInfo(prePaySchChargeVO.getCreator());
			prePaySchChargeVO.setSysDate(sysInfo.getSysDate());
		}
		//生成凭证
		VoucherDomain voucher = this.createVoucher(prePaySchChargeVO, sysInfo);
		prePaySchChargeVO.setVoucherId(voucher.getVoucherId());

		this.addCreditTransAction(prePaySchChargeVO, sysInfo);

		return prePaySchChargeVO;
	}

	/**
	 * 功能描述: 针对同一个预交款子账户，添加多笔预交款收款交易  <br>
	 * @param operator 操作者ID
	 * @param accountHouseId 账户所属房屋的ID
	 * @param prePaySchChargeVOs预交款账户收款VO集
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-9  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public List<PrePaySchChargeVO> addPrePayChargeTransactionBatch(Long operator,Long accountHouseId,List<PrePaySchChargeVO> prePaySchChargeVOs){
		super.checkParameterIsNull("common:parameters_null_exception, ",operator,accountHouseId,prePaySchChargeVOs);

		// 查找房间收费账户
		AccountDomain account = this.accountService.getCurrentAccount(accountHouseId);
		Long accountId = account.getAccountId();
		PrePayAccountDomain  prePayAccount  = this.accountService.getPrePayAccountByAccount(account);
		Long subAccountId = prePayAccount.getSubAccountId();
		// 判断子账户贷方是否锁定
		Boolean isLock = this.subAccountService.isLockCredit(subAccountId);
		if (isLock) {
			throw new BusinessException("charge:charge_account_credit_locked_exception",
										BusinessException.WARNING);
		}
		//查找当前收费周期
		PeriodVO periodVo = this.periodService.queryCurrentPeriod();
		// 查找所在收费管理区号
		PrecinctVO precinctVO  = this.houseService.getPrecinctVOByHouseId(accountHouseId, null);
		SysInfo sysInfo = super.createInfo(operator);
		for (PrePaySchChargeVO chargeVO : prePaySchChargeVOs) {
			chargeVO.setAccountId(accountId);
			chargeVO.setSubAccountId(subAccountId);
			chargeVO.setPeriodId(periodVo.getPrecinctID());
			chargeVO.setPrecinctCode(precinctVO.getPrecinctCode());
			// 收款交易类型007
			chargeVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_PRERECEIVABLES);
			// 凭证号前缀YJK
			chargeVO.setVoucherNoPrefix(SysrefcodeDO.EINZUG_VOUCHERNO_PREFIX);
			// 生成凭证
			VoucherDomain voucher = this.createVoucher(chargeVO, sysInfo);
			chargeVO.setVoucherId(voucher.getVoucherId());

			this.addCreditTransAction(chargeVO, sysInfo);
		}

		return prePaySchChargeVOs;
	}

	/**
	 * 功能描述:　
	 * 　<ul><li>添加一笔本金交易 </li></ul>
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:付湘辉  <br>
	 * Edit on: 2009-1-07   <br>
	 * Why:建议使用接口：addDebitPrincipalTransaction     <br>
	 */
	@Deprecated
	public DebitTransVO addPrincipalTransaction(DebitTransVO debitTransVO){
		super.checkParameterIsNull(debitTransVO, "common:parameters_null_exception, ");

		//判断子账户借方是否锁定
		Boolean isLock = this.subAccountService.isLockDebit(debitTransVO.getSubAccountId());
		if (isLock) {
			throw new BusinessException("charge:charge_account_debit_locked_exception",
										BusinessException.WARNING);
		}
		//交易类型是本金交易
		debitTransVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_PRINCIPAL);
		//交易状态是未缴
		debitTransVO.setStatuz(SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY);

		this.addDebitTransAction(debitTransVO);

		DebitTransDomain debitDo = (DebitTransDomain)this.transactionDao.findById(debitTransVO.getTransactionId());
		//主交易id(冗余字段)
		debitDo.setMTransId(debitTransVO.getTransactionId());
		return debitTransVO;
	}

	/**
	 * 功能描述:<ul><li>添加多笔本金交易 </li></ul>
	 * @param operator
	 * @param subAccountId
	 * @param debitTransVOs
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-12-29  <br>
	 * Edit author:付湘辉  <br>
	 * Edit on:2009-1-7     <br>
	 * Why:建议调用 addDebitPrincipalTransactionBatch    <br>
	 */
	@Deprecated
	public List<DebitTransVO> addPrincipalTransactionBatch(Long operator,Long subAccountId,List<DebitTransVO> debitTransVOs){
		super.checkParameterIsNull("common:parameters_null_exception, ",operator,subAccountId,debitTransVOs );

		//判断子账户借方是否锁定
		Boolean isLock = this.subAccountService.isLockDebit(subAccountId);
		if (isLock) {
			throw new BusinessException("charge:charge_account_debit_locked_exception",
										BusinessException.WARNING);
		}
		SysInfo sysInfo = super.createInfo(operator);
		BigDecimal debitTotal = BigDecimalUtil.getZEROInstance();
		for (Iterator<DebitTransVO> iter = debitTransVOs.iterator(); iter.hasNext();) {
			DebitTransVO debitTransVO = iter.next();
			// 交易类型是本金交易
			debitTransVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_PRINCIPAL);
			// 交易状态是未缴
			debitTransVO.setStatuz(SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY);
			debitTransVO.setSysDate(sysInfo.getSysDate());

			debitTransVO = this.addDebitTransAction(debitTransVO,sysInfo);

			DebitTransDomain debitDo = (DebitTransDomain)this.transactionDao.findById(debitTransVO.getTransactionId());
			//主交易id(冗余字段)
			debitDo.setMTransId(debitTransVO.getTransactionId());
			//累加应收金额，用于更新帐户余额
			debitTotal=debitTotal.add(debitTransVO.getDebit());
		}

		// 更新帐户余额
		Map<Long, BigDecimal> subAccountIDBalances = new HashMap<Long, BigDecimal>();
		subAccountIDBalances.put(subAccountId, debitTotal);
		this.subAccountDao.updateSubAccountBalanceBatchAdd(subAccountIDBalances);

		return debitTransVOs;
	}

	/**
	 * 功能描述:　
	 * 　<ul><li>添加一笔减免交易 </li></ul>
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public AdjustTransactionVO addReliefTransaction(AdjustTransactionVO reliefTransVO){
		super.checkParameterIsNull(reliefTransVO, "common:parameters_null_exception, ");

		//判断减免后金额
		if (1 == BigDecimal.ZERO.compareTo(reliefTransVO.getReliefBalance())) {
			throw new BusinessException("charge:charge_relief_not_negative_exception",
										BusinessException.WARNING);
		} else if (0 == BigDecimal.ZERO.compareTo(reliefTransVO.getReliefBalance())) {
			//交易状态是全额减免
			reliefTransVO.setStatuz(SysrefcodeDO.FEE_TRANSACTION_STATUZ_DERATE);
			try {
				//得到主交易
				DebitTransDomain masterTrans = (DebitTransDomain) this.transactionDao
						.findById(reliefTransVO.getPrincipalTrans()
								.getTransactionId());
				this.changeTransStatus(masterTrans,
						SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY,
						SysrefcodeDO.FEE_TRANSACTION_STATUZ_DERATE,
						reliefTransVO.getCreator(), false, super.getDate());
			} catch (ClassCastException ce) {
				super.logger.fatal(ce.getMessage(), ce);
				throw new BusinessException(
							"charge:charge_assign_trans_isnot_debit_exception",
							BusinessException.WARNING);
			}
		}
		//交易类型是减免交易
		reliefTransVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_RELIEF);
		//设置减免金额为负数
		reliefTransVO.setDebit(reliefTransVO.getDebit().abs().negate());

		reliefTransVO.setInputDate(super.getDate());
		//在备注字段中加入衍生交易的交易摘要说明
		this.dealDerivativeTransRemark(reliefTransVO);

		//增加一笔应收交易
		this.addDebitTransAction(reliefTransVO);

		//添加一笔交易关系表记录，关系类型为减免
		this.dealTransactionRelation(reliefTransVO.getPrincipalTrans(),
					reliefTransVO,
					SysrefcodeDO.FEE_TRA_R_TRA_RELATION_TYPE_RELIEF);

		return reliefTransVO;
	}

	/**
	 * 功能描述: 检查指定的账户下是否有挂起的交易 <br>
	 * @param accountId 总账户id
	 * @return true 有  false 没有
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-11-6  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public Boolean checkAccountHasHangsTransaction(Long accountId){
		super.checkParameterIsNull(accountId, "common:parameters_null_exception, ");
		AccountDomain account = this.accountService.getAccountDoById(accountId);

		Long subAccountId = null;
		for (AbstractSubAccount subAccount : account.getSubAccounts()) {
			if (subAccount instanceof ChargeAccountDomain) {
				subAccountId = subAccount.getSubAccountId();
				break;
			}
		}
		Long counts =
			this.transactionDao.getTransactionCountByIdStatus(subAccountId,
							 	 SysrefcodeDO.FEE_TRANSACTION_STATUZ_HANGED);
		return counts > 0l;
	}

	/**
	 * 功能描述: 根据主易id初始化一条调整交易VO,用于初始化调整操作 <br>
	 * @param transId 主交易id
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public AdjustTransactionVO getAdjustTransByMasterId(Long transId){
		return this.initializeAdjustTransByMasterId(transId,SysrefcodeDO.CONSTANTS_DIGITAL_ONE);
	}

	/**
	 * 功能描述: 根据传入id查询一个实收交易，如果查出来不是实收交易将抛异常 <br>
	 * @param creditTransId
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-9  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public CreditTransVO getCreditTransVOById(Long creditTransId){
		return this.getCreditTransVOById(creditTransId, false);
	}

	/**
	 * 功能描述: 根据传入id查询一个实收交易，如果查出来不是实收交易将抛异常 <br>
	 * @param creditTransId
	 * @param withDetail 是否查询明细信息
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-9  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public CreditTransVO getCreditTransVOById(Long creditTransId,Boolean withDetail){
		AbstractTransVO transVo = this.getAbstractTransVOById(creditTransId);
		CreditTransVO creditVo = checkCreditInstance(transVo);
		if (!BlankUtil.isBlank(withDetail) && withDetail) {
			this.dealPayTransDetail(creditVo);
		}
		return creditVo;
	}

	/**
	 * 功能描述: 根据传入id查询一个应收交易，如果查出来不是应收交易将抛异常 <br>
	 * @param debitTransId
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-9  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public DebitTransVO getDebitTransVOById(Long debitTransId){
		AbstractTransVO transVo = this.getAbstractTransVOById(debitTransId);

		DebitTransVO debitVo = getDebitInstance(transVo);

		return debitVo;
	}

	/**
	 * 功能描述: 查询指定id的滞纳金的明细列表 <br>
	 * @param lateTransId
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-18  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public List<LateFeeDetailVO> getLateFeeDetailListById(Long lateTransId){
		super.checkParameterIsNull(lateTransId, "common:parameters_null_exception,ID");
		List<LateFeeDetailVO> list = new ArrayList<LateFeeDetailVO>();
		DebitTransDomain debit=null;
		AbstractTrans trans = this.transactionDao.findById(lateTransId);

		if (trans instanceof DebitTransDomain) {
			debit = (DebitTransDomain)trans;
		}else{
			throw new BusinessException("charge:charge_assign_trans_isnot_debit_exception",
					BusinessException.WARNING);
		}


		Set<LatefeeDetail> set =  debit.getLateFees();
		Iterator<LatefeeDetail> iter = set.iterator();
		while (iter.hasNext()) {
			LatefeeDetail lateDetailDo = iter.next();
			LateFeeDetailVO lateDetailVo = new LateFeeDetailVO();

			BeanUtil.convertVoAsDo(lateDetailDo, lateDetailVo);

			lateDetailVo.setRootTransId(lateDetailDo.getMTransId());

			//计算天数
			Date startDate = lateDetailVo.getStartDate();
			Date endDate = lateDetailVo.getEndDate();
			lateDetailVo.setDays(new Long(DateUtil.getDays(startDate, endDate)+1));
			//滞纳金计算公式
			lateDetailVo.setCalculationMethod(getCalculateLateFeeFormula(lateDetailVo.getBaseAmt(),
					new Long(DateUtil.getDays(startDate, endDate)+1), lateDetailVo.getRate(),lateDetailVo.getLatefee()));

			DebitTransDomain debitTrans = lateDetailDo.getDebitTrans();
			if (!BlankUtil.isBlank(debitTrans)) {
				BusinessCodeDomain buscode = debitTrans.getBusinessCode();
				lateDetailVo.setTransName(buscode.getBizCode()+"-"+buscode.getDescription());
			}
			list.add(lateDetailVo);
		}
		//滞纳金合计
		LateFeeDetailVO total = new LateFeeDetailVO();
		total.setLatefee(debit.getDebit());
		list.add(total);
		return list;
	}

	/**
	 * 功能描述: 获取出盘锁定状态的交易数量 <br>
	 * @param status
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-10-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public Integer getOutLocakTransactionCount(){
		Integer counts = this.transactionDao.getOutLocakTransactionCount();
		return counts;
	}

	/**
	 * 功能描述: 根据主易id初始化一条减免交易VO,用于初始化减免操作 <br>
	 * @param transId 主交易id
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-4  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public AdjustTransactionVO getReliefTransByMasterId(Long transId){
		AdjustTransactionVO adjustTransVo =  this.initializeAdjustTransByMasterId(transId,SysrefcodeDO.CONSTANTS_DIGITAL_TWO);
		if (0 == BigDecimal.ZERO.compareTo(adjustTransVo.getCurTransPrice())) {
			throw new BusinessException(
					"charge:charge_curtransprice_is_zero_exception",
					BusinessException.WARNING);
		}
		return adjustTransVo;
	}

    /**
	 * 功能描述: 查询指定条件的交易，用于显示列表 <br>
	 * @param searchVo
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-3  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public List<TransactionVO> getTransactionVoByConditions(ChargeDetailSearchVO searchVo){
		super.checkParameterIsNull("common:parameters_null_exception, ",searchVo);
		super.checkParameterIsNull("common:parameters_null_exception,ID",searchVo.getAccountId());
		this.dealChargeSubAccountId(searchVo);

		List<TransactionVO> transVoList = this.getTransactionVoList(searchVo);
		final int size = transVoList.size();
		int i=0;

		BigDecimal total = new BigDecimal("0.00",BigDecimalUtil.getMathContext());

		//遍历找出每个交易的父和子
		for (i = 0; i < size; i++) {
			TransactionVO transVo = transVoList.get(i);

			if (canFindSon(transVo.getClazz())) {//查找子交易
				Set<TransactionVO> childrens= new HashSet<TransactionVO>();
				for (int j = 0; j < size; j++) {
					TransactionVO children = transVoList.get(j);
					if (transVo.getTransactionId().equals(children.getParentId())) {
						childrens.add(children);
					}
				}
				transVo.setChildren(childrens);
			}

			if(canFindFather(transVo.getClazz())){//查找父交易
				int k = 0;
				for (; k < size; k++) {
					TransactionVO parent = transVoList.get(k);
					if (parent.getTransactionId().equals(transVo.getParentId())) {
						transVo.setParent(parent);
						break;
					}
				}

				if (k == size){//当调整、减免或滞纳金单独存在时
					transVo.setParentId(null);
					transVo.setParent(null);
				}
			}

			//如果查出了实收交易
			if (SysrefcodeDO.FEE_TRANSACTION_CLAZZ_MAINPAY.equals(transVo.getClazz())) {
				total=total.add(transVo.getPrice().negate(),BigDecimalUtil.getMathContext());
			}else{
				total=total.add(transVo.getPrice(),BigDecimalUtil.getMathContext());
			}

		}

		TransactionVO totalTransVo=new TransactionVO();
		totalTransVo.setPrice(total);
		transVoList.add(totalTransVo);

		return transVoList;
	}

    /**
	 * 功能描述:  针对同一个物业帐户，处理多次入账收费过程，每次过程包括增加应收和实收交易两个子业务。
	 * 除必须项外，在参数debitTransVOs中每个应收都应该包含交易码信息，
	 * 在creditTransVOs中每个实收都应该有交易码信息。
	 * debitTransVOs中的数量应该与creditTransVOs中数量一致<br>
	 * @param operator 操作者ID
	 * @param accountHouseId 账户所属房屋的ID
	 * @param debitTransVO  应收交易VO集
	 * @param creditTransVO 实收交易VO集
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public Boolean handleMultiCharge(Long operator,Long accountHouseId,List<DebitTransVO> debitTransVOs,List<CreditTransVO> creditTransVOs){
		super.checkParameterIsNull("common:parameters_null_exception, ",operator,accountHouseId,debitTransVOs,creditTransVOs);
		if (debitTransVOs.size() !=  creditTransVOs.size()) {
			throw new BusinessException("charge:charge_transaction_digit_not_equals_exception",
									BusinessException.WARNING);
		}
		//查找房间收费账户
		AccountDomain account = this.accountService.getCurrentAccount(accountHouseId);
		ChargeAccountDomain chargeAccount  = this.accountService.getChargeAccountByAccount(account);
		Long subAccountId = chargeAccount.getSubAccountId();
		//查找当前收费周期
		PeriodVO periodVo = this.periodService.queryCurrentPeriod();
		Long periodId = periodVo.getKeyword();
		for (Iterator<DebitTransVO> iter = debitTransVOs.iterator(); iter.hasNext();) {
			DebitTransVO transVO = iter.next();
			transVO.setSubAccountId(subAccountId);
			transVO.setPeriodId(periodId);
		}

		//批量入账
		debitTransVOs = this.addPrincipalTransactionBatch(operator, subAccountId, debitTransVOs);
		// 判断子账户贷方是否锁定
		Boolean isLock = this.subAccountService.isLockCredit(subAccountId);
		if (isLock) {
			throw new BusinessException("charge:charge_account_credit_locked_exception",
										BusinessException.WARNING);
		}
		// 查找所在收费管理区号
		PrecinctVO precinctVO  = this.houseService.getPrecinctVOByHouseId(accountHouseId, null);
		SysInfo sysInfo = super.createInfo(operator);
		final int size = debitTransVOs.size();
		for (int i = 0; i < size; i++) {
			DebitTransVO debitTransVo = debitTransVOs.get(i);
			debitTransVo.setReceivablePrice(debitTransVo.getDebit());

			CreditTransVO creditTransVo = creditTransVOs.get(i);
			// 填充实收交易VO
			creditTransVo.setAccountId(account.getAccountId());
			creditTransVo.setSubAccountId(chargeAccount.getSubAccountId());
			creditTransVo.setPeriodId(periodId);
			creditTransVo.setPrecinctCode(precinctVO.getPrecinctCode());
			creditTransVo.getDebits().add(debitTransVo);
			creditTransVo.setCredit(debitTransVo.getDebit());
			creditTransVo.setCreator(operator);
			//缴费处理：增加一笔实收交易
			creditTransVo = this.addChargeTransactionInner(creditTransVo, sysInfo);
		}
		return true;
	}

    /**
	 * 功能描述:  针对同一个物业帐户，处理一次入账收费过程，包括增加应收和实收交易两个子业务。
	 * 除必须项外，在参数debitTransVO应包含交易码信息，
	 * 在creditTransVO中应有交易码信息。 <br>
	 * @param operator 操作者ID
	 * @param accountHouseId 账户所属房屋的ID
	 * @param debitTransVO  应收交易VO
	 * @param creditTransVO 实收交易VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public Boolean handleOneCharge(Long operator,Long accountHouseId,DebitTransVO debitTransVO,CreditTransVO creditTransVO){
		super.checkParameterIsNull("common:parameters_null_exception, ",operator,accountHouseId,debitTransVO,creditTransVO);
		//查找房间收费账户
		AccountDomain account = this.accountService.getCurrentAccount(accountHouseId);
		ChargeAccountDomain chargeAccount  = this.accountService.getChargeAccountByAccount(account);
		debitTransVO.setSubAccountId(chargeAccount.getSubAccountId());
		//查找当前收费周期
		PeriodVO periodVo = this.periodService.queryCurrentPeriod();

		// 查找所在收费管理区号
		PrecinctVO precinctVO  = this.houseService.getPrecinctVOByHouseId(accountHouseId, null);
		creditTransVO.setPrecinctCode(precinctVO.getPrecinctCode());
		return handleOneChargeInner(operator, accountHouseId, debitTransVO, creditTransVO, account, chargeAccount, periodVo);
	}

    /**
	 * 功能描述: 挂起操作 <br>
	 * @param debitVo
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-17  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public Boolean hangsTransaction(DebitTransVO debitVo){
		super.checkParameterIsNull("common:parameters_null_exception, ",debitVo);
		super.checkParameterIsNull("common:parameters_null_exception, ",
				debitVo.getTransactionId(),
				debitVo.getClazz(),
				debitVo.getModifier());

		if (!(debitVo.isDebitTransaction()
				||SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY.equals(debitVo.getStatuz()))) {
			//不是应收未缴交易不能作挂起操作
			throw new BusinessException("charge:charge_hangs_not_debit_nopay_exception",
					BusinessException.WARNING);
		}

		try {
			AbstractTrans abstractTrans = this.transactionDao.findById(debitVo.getTransactionId());
			Long subAccountId = abstractTrans.getBindingAccount().getSubAccountId();
			// 判断子账户借方是否锁定
			Boolean isLock = this.subAccountService.isLockDebit(subAccountId);
			if (isLock) {
				throw new BusinessException("charge:charge_account_debit_locked_exception",
											BusinessException.WARNING);
			}
			BigDecimal moneyAmount = ((DebitTransDomain)abstractTrans).getDebit();
			//修改状态为挂起并返回各子交易的金额和
			BigDecimal total = this.changeTransStatus((DebitTransDomain)abstractTrans,
					SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY,
					SysrefcodeDO.FEE_TRANSACTION_STATUZ_HANGED,
					debitVo.getModifier(), true, super.getDate());

			moneyAmount = moneyAmount.add(total,BigDecimalUtil.getMathContext());
//			abstractTrans.calculationHangsBalance(moneyAmount, false);
			Map<Long, BigDecimal> subAccountIDBalances = new HashMap<Long, BigDecimal>();
			subAccountIDBalances.put(subAccountId, moneyAmount);
			this.subAccountDao.updateSubAccountBalanceBatchSub(subAccountIDBalances);

			return true;
		} catch(BusinessException be){
			throw be;
		} catch (Exception e) {
			super.logger.fatal(e.getMessage(), e);
			throw new BusinessException("charge:charge_hangs_failure_exception",
					BusinessException.WARNING);
		}
	}

	/**
	 * 功能描述: 解除挂起操作 <br>
	 * @param debitVo
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-17  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public Boolean liftingHangsTransaction(DebitTransVO debitVo){
		super.checkParameterIsNull("common:parameters_null_exception, ",debitVo);
		super.checkParameterIsNull("common:parameters_null_exception, ",
				debitVo.getTransactionId(),
				debitVo.getClazz(),
				debitVo.getModifier());

		if (!debitVo.isDebitTransaction()) {
			//不是应收交易不能进行解除挂起操作
			throw new BusinessException("charge:charge_hangs_not_debit_nopay_exception",
					BusinessException.WARNING);
		}
		try {
			AbstractTrans abstractTrans = this.transactionDao.findById(debitVo.getTransactionId());

			Long subAccountId = abstractTrans.getBindingAccount().getSubAccountId();
			// 判断子账户借方是否锁定
			Boolean isLock = this.subAccountService.isLockDebit(subAccountId);
			if (isLock) {
				throw new BusinessException("charge:charge_account_debit_locked_exception",
											BusinessException.WARNING);
			}

			BigDecimal moneyAmount = ((DebitTransDomain)abstractTrans).getDebit();
			//修改状态为挂起并返回各子交易的金额和
			BigDecimal total = this.changeTransStatus((DebitTransDomain)abstractTrans,
								SysrefcodeDO.FEE_TRANSACTION_STATUZ_HANGED,
								SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY,
								debitVo.getModifier(), true, super.getDate());

//			abstractTrans.calculationHangsBalance(moneyAmount, true);
			moneyAmount = moneyAmount.add(total,BigDecimalUtil.getMathContext());
			Map<Long, BigDecimal> subAccountIDBalances = new HashMap<Long, BigDecimal>();
			subAccountIDBalances.put(subAccountId, moneyAmount);
			this.subAccountDao.updateSubAccountBalanceBatchAdd(subAccountIDBalances);
			return true;
		} catch(BusinessException be){
			throw be;
		} catch (Exception e) {
			super.logger.fatal(e.getMessage(), e);
			throw new BusinessException("charge:charge_hangs_failure_exception",
					BusinessException.WARNING);
		}
	}

	/**
	 * 功能描述:进行一次押金抵冲过程，
	 * 先针对押金账户进行一次退款,再针对物业账户新增一笔应收和一笔实收交易，
	 * 并建立相应的交易关系。  <br>
	 * @param debitBusinessId 应收交易码ID
	 * @param creditBusinessId 实收交易码ID
	 * @param depositTransVO 押金VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-14  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public Boolean offsetOneDepositCharge(Long debitBusinessId,Long creditBusinessId,DepositTransVO depositTransVO){
		super.checkParameterIsNull("common:parameters_null_exception, ",debitBusinessId,creditBusinessId,depositTransVO);
		super.checkParameterIsNull("common:parameters_null_exception, ",
														depositTransVO.getAccountHouseId(),
														depositTransVO.getCreator(),
														depositTransVO.getBusinessId(),
														depositTransVO.getCredit(),
														depositTransVO.getHouseId());
		//查找房间收费账户
		AccountDomain account = this.accountService.getCurrentAccount(depositTransVO.getAccountHouseId());
		depositTransVO.setAccountId(account.getAccountId());
		//得到押金子账户
		DepositAccountDO depositAccount = this.accountService.getDepositAccountByAccount(account);
		depositTransVO.setSubAccountId(depositAccount.getSubAccountId());
		//得到物业子账户
		ChargeAccountDomain chargeAccount  = this.accountService.getChargeAccountByAccount(account);
		//查找当前收费周期
		PeriodVO periodVo = this.periodService.queryCurrentPeriod();
		depositTransVO.setPeriodId(periodVo.getKeyword());
		depositTransVO.setPeriod(periodVo.getPeriod());

		// 查找所在收费管理区号
		PrecinctVO precinctVO  = this.houseService.getPrecinctVOByHouseId(depositTransVO.getAccountHouseId(), null);
		depositTransVO.setPrecinctCode(precinctVO.getPrecinctCode());
		// 押金抵冲交易类型010
		depositTransVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_DEPOSIT_TOUCH);
		SysInfo sysInfo = super.createInfo(depositTransVO.getCreator());

		depositTransVO.setCredit(depositTransVO.getCredit().abs().negate());
		// 新增一笔押金抵冲交易
		depositTransVO = this.addOneDepositTransVOInner(depositTransVO, sysInfo);
		DebitTransVO debitTransVO = new DebitTransVO(depositTransVO.getAccountHouseId(),
													debitBusinessId,
													depositTransVO.getHouseId(),
													depositTransVO.getCreator(),
													depositTransVO.getCredit().abs());

		debitTransVO.setRemark(depositTransVO.getRemark());

		CreditTransVO creditTransVO = new CreditTransVO(depositTransVO.getAccountHouseId(),creditBusinessId,depositTransVO.getCreator(),null,debitTransVO.getDebit(),new HashSet<DebitTransVO>());
		creditTransVO.setPrecinctCode(precinctVO.getPrecinctCode());
		creditTransVO.setRemark(depositTransVO.getRemark());
		//新增应收与实收
		this.handleOneChargeInner(depositTransVO.getCreator(), depositTransVO.getAccountHouseId(), debitTransVO, creditTransVO, account, chargeAccount, periodVo);
		//建立押金抵冲关系
		this.createDepositOffsetRelation(creditTransVO,depositTransVO);
		return true;
	}

	/**
	 * 功能描述:查询押金子账户的相关押金收款交易分页列表。  <br>
	 * @param depositTransSearchVO 总账户ID
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-9  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	@SuppressWarnings("unchecked")
	public Page queryDepositTransVOByPage(DepositTransSearchVO depositTransSearchVO){
		Assert.notNull(depositTransSearchVO);
		Assert.notNull(depositTransSearchVO.getAccountId());
		depositTransSearchVO.checkRule();
		if (BlankUtil.isBlank(depositTransSearchVO.getSubAccountId())) {
			DepositAccountDO  depositAccount = this.accountService.getDepositAccountByAccountId(depositTransSearchVO.getAccountId());
			depositTransSearchVO.setSubAccountId(depositAccount.getSubAccountId());
		}

		Page page = this.transactionDao.queryDepositTransVOByPage(depositTransSearchVO);
		List<CreditTransDomain> list = page.getResult();
		List<DepositTransVO> resList = new ArrayList<DepositTransVO>();
		synchronized (this) {
			this.initTransClazzMap();
			this.initHmployeeNameCache();
			for (CreditTransDomain domain : list) {
				DepositTransVO tempVo = new DepositTransVO();
				assembleCreditDO2DepositTransVO(domain, tempVo);
				tempVo.setClazzName(this.transClazzMap.get(tempVo.getClazz()));
				if (tempVo.getCreator() != null) {
					// 操作人名称
					if (this.hmployeeNameCacheMap.get(tempVo.getCreator())==null) {
						this.hmployeeNameCacheMap.put(tempVo.getCreator(), this.secUserService.queryUserNameById(tempVo.getCreator()));
					}
					tempVo.setOpratorName(this.hmployeeNameCacheMap.get(tempVo.getCreator()));
				}
				resList.add(tempVo);
			}
			this.destoreHmployeeCache();
			this.destoreTransClazzCache();
		}
		page.setResult(resList);
		return page;
	}

	/**
	 * @param accountService the accountService to set
	 */
	public void setAccountService(IAccountService accountService) {
		this.accountService = accountService;
	}


	/**
	 * @param businessCodeDao the businessCodeDao to set
	 */
	public void setBusinessCodeDao(IBusinessCodeDao businessCodeDao) {
		this.businessCodeDao = businessCodeDao;
	}

	/**
	 * @param chargeStaDao the chargeStaDao to set
	 */
	public void setChargeStaDao(IChargeStaDao chargeStaDao) {
		this.chargeStaDao = chargeStaDao;
	}

	public void setChargeVoucherDao(IChargeVoucherDao chargeVoucherDao) {
		this.chargeVoucherDao = chargeVoucherDao;
	}

	/**
	 * @param houseService the houseService to set
	 */
	public void setHouseService(IHouseService houseService) {
		this.houseService = houseService;
	}

	/**
	 * @param periodService the periodService to set
	 */
	public void setPeriodService(IPeriodService periodService) {
		this.periodService = periodService;
	}

	public void setSecUserService(ISecUserService secUserService) {
		this.secUserService = secUserService;
	}

	/**
	 * @param subAccountDao the subAccountDao to set
	 */
	public void setSubAccountDao(ISubAccountDao subAccountDao) {
		this.subAccountDao = subAccountDao;
	}

	public void setSubAccountService(ISubAccountService subAccountService) {
		this.subAccountService = subAccountService;
	}


	/**
	 * @param transactionDao the transactionDao to set
	 */
	public void setTransactionDao(ITransactionDao transactionDao) {
		this.transactionDao = transactionDao;
	}

	/**
	 * 功能描述:  <br>
	 * @param creditTransVO
	 * @param sysInfo
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-9  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private CreditTransVO addChargeTransactionInner(CreditTransVO creditTransVO,SysInfo sysInfo){
		if (BlankUtil.isBlank(creditTransVO.getDebits())) {
			throw new BusinessException("charge:charge_transaction_not_debittrans_exception",
					BusinessException.WARNING);
		}

		this.checkMultiplePayPrice(creditTransVO);

		//收费交易类型005
		creditTransVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_MAINPAY);
		//凭证号前缀JFT
		creditTransVO.setVoucherNoPrefix(SysrefcodeDO.CHARGE_VOUCHERNO_PREFIX);

		creditTransVO.setSysDate(sysInfo.getSysDate());

		//生成凭证
		VoucherDomain voucher = this.createVoucher(creditTransVO, sysInfo);
		creditTransVO.setVoucherId(voucher.getVoucherId());

        //增加主支付交易
		creditTransVO = this.addCreditTransAction(creditTransVO, sysInfo);
		//处理一笔主支付交易的子支付交易(如果是多重支付生效)
		Set<CreditTransVO> sets = dealSubPayTrans(creditTransVO);

        //查询出主支付交易实体
		AbstractTrans mainPayTrans = this.transactionDao.findById(creditTransVO.getTransactionId());

        // 处理应收-实收关系
        this.dealDebitAndCreditRelation(creditTransVO, mainPayTrans);

		//处理多重支付时主支付与子支付关系
		this.dealMainPayAndSubForMultiple(sets, mainPayTrans);

		this.transactionDao.updateObject(mainPayTrans);

		return creditTransVO;
	}

	/**
	 * 功能描述: 增加一笔实收交易 <br>
	 * @param creditTransVO
	 * @param sysInfo TODO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private CreditTransVO addCreditTransAction(CreditTransVO creditTransVO, SysInfo sysInfo){
		try {
			super.checkParameterIsNull(creditTransVO, "common:parameters_null_exception, ");
			super.checkParameterIsNull("common:parameters_null_exception,ID",creditTransVO.getAccountId(),creditTransVO.getSubAccountId());

			CreditTransDomain creditDo = this.assembleV2D(creditTransVO);
			creditDo.setSysInfo(sysInfo);

			//检查必须字段
			creditDo.checkRequiredField();

			this.transactionDao.saveObject(creditDo);
			//计算帐户余额
			Map<Long, BigDecimal> subAccountIDBalances = new HashMap<Long, BigDecimal>();
			subAccountIDBalances.put(creditDo.getBindingAccount().getSubAccountId(), creditDo.getCredit());
			this.subAccountDao.updateSubAccountBalanceBatchSub(subAccountIDBalances);

			creditTransVO.setTransactionId(creditDo.getTransactionId());
		} catch (BusinessException be) {
			throw be;
		} catch (Exception e) {
			super.logger.fatal(e.getMessage(),e);
			throw new BusinessException("charge:charge_charge_addcredit_failure_exception",
																BusinessException.FAILURE);
		}

		return creditTransVO;
	}

	/**
	 * 功能描述: 增加一笔应收交易 <br>
	 * @param debitTransVO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private DebitTransVO addDebitTransAction(DebitTransVO debitTransVO){
		super.checkParameterIsNull(debitTransVO, "common:parameters_null_exception, ");
		super.checkCreatorInfo(debitTransVO.getCreator());

		SysInfo sysInfo = null;
		if (!BlankUtil.isBlank(debitTransVO.getSysDate())) {
			sysInfo = new SysInfo();
			sysInfo.setCreator(debitTransVO.getCreator());
			sysInfo.setSysDate(debitTransVO.getSysDate());
		}else{
			sysInfo = super.createInfo(debitTransVO.getCreator());
			debitTransVO.setSysDate(sysInfo.getSysDate());
		}

		debitTransVO =  this.addDebitTransAction(debitTransVO, sysInfo);
		// 计算帐户余额
		Map<Long, BigDecimal> subAccountIDBalances = new HashMap<Long, BigDecimal>();
		subAccountIDBalances.put(debitTransVO.getSubAccountId(), debitTransVO.getDebit());
		this.subAccountDao.updateSubAccountBalanceBatchAdd(subAccountIDBalances);

		return debitTransVO;
	}

	/**
	 * 功能描述: 增加一笔应收交易 <br>
	 * @param debitTransVO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private DebitTransVO addDebitTransAction(DebitTransVO debitTransVO,SysInfo sysInfo){
		try {
			super.checkParameterIsNull(sysInfo, "common:parameters_null_exception, ");

			DebitTransDomain debitDo = this.assembleV2D(debitTransVO);
			debitDo.setSysInfo(sysInfo);

			//检查必须字段
			debitDo.checkRequiredField();

			this.checkInputDate(debitDo.getInputDate(), sysInfo.getSysDate());

			this.transactionDao.saveObject(debitDo);

			debitTransVO.setTransactionId(debitDo.getTransactionId());
		} catch (BusinessException be) {
			throw be;
		} catch (Exception e) {
			super.logger.fatal(e.getMessage(),e);
			throw new BusinessException("charge:charge_input_account_failure_exception",BusinessException.FAILURE);
		}

		return debitTransVO;
	}

	/** 功能描述:  <br>
	 * @param depositTransVO
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-13  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private DepositTransVO addOneDepositTransVOInner(DepositTransVO depositTransVO,SysInfo sysInfo) {
		// 凭证号前缀YAJ
		depositTransVO.setVoucherNoPrefix(SysrefcodeDO.DEPOSIT_VOUCHERNO_PREFIX);
		depositTransVO.setSysDate(sysInfo.getSysDate());
		//生成凭证
		VoucherDomain voucher = this.createVoucher(depositTransVO, sysInfo);
		depositTransVO.setVoucherId(voucher.getVoucherId());

		this.addCreditTransAction(depositTransVO, sysInfo);

		return depositTransVO;
	}

	/**
	 * 功能描述: 添加一笔交易关系 <br>
	 * @param masterTrans 主交易
	 * @param relationTrans 关联交易
	 * @param relationType 关系类型
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-6  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private TraRtra addOneTransactionRelation(AbstractTrans masterTrans,AbstractTrans relationTrans,String relationType){
		TraRtra trt = new TraRtra();
		trt.setMasterTrans(masterTrans);//主交易
		trt.setRelatingTrans(relationTrans);//附属交易
		trt.setRelatingType(relationType);//设置关系类型
		try {
			masterTrans.getTraRtras().add(trt);
		} catch (Exception e) {
			super.logger.fatal(e.getMessage(), e);
			throw new BusinessException("charge:charge_add_trans_relation_failure_exception",
						BusinessException.WARNING);
		}
		return trt;
	}

	/**
	 * 功能描述: 增加一笔子支付交易 <br>
	 * @param creditTransVO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private CreditTransVO addSubsidiaryPayCreditTransAction(CreditTransVO creditTransVO){
		try {
			SysInfo sysInfo = null;
			if (!BlankUtil.isBlank(creditTransVO.getSysDate())) {
				sysInfo = new SysInfo();
				sysInfo.setCreator(creditTransVO.getCreator());
				sysInfo.setSysDate(creditTransVO.getSysDate());
			}else{
				sysInfo = super.createInfo(creditTransVO.getCreator());
				creditTransVO.setSysDate(sysInfo.getSysDate());
			}
			CreditTransDomain creditDo = this.assembleV2D(creditTransVO);
			creditDo.setSysInfo(sysInfo);

			//检查必须字段
			creditDo.checkRequiredField();

			this.transactionDao.saveObject(creditDo);

			creditTransVO.setTransactionId(creditDo.getTransactionId());
		} catch (BusinessException be) {
			throw be;
		} catch (Exception e) {
			super.logger.fatal(e.getMessage(),e);
			throw new BusinessException("charge:charge_input_account_failure_exception",BusinessException.FAILURE);
		}

		return creditTransVO;
	}

	/** 功能描述:  <br>
	 * @param transDo
	 * @param transVo
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-9  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void assembleCreditDO2DepositTransVO(CreditTransDomain transDo, DepositTransVO transVo) {
		BeanUtil.convertVoAsDo(transDo, transVo);
		AbstractSubAccount subAccount = transDo.getBindingAccount();
		if (!BlankUtil.isBlank(subAccount)) {
			transVo.setSubAccountId(subAccount.getSubAccountId());
			transVo.setAccountId(subAccount.getAccount().getAccountId());
		}

		BusinessCodeDomain busCode = transDo.getBusinessCode();
		if (!BlankUtil.isBlank(busCode)) {
			transVo.setBusinessId(busCode.getKeyword());
			transVo.setBizCode(busCode.getBizCode());
			transVo.setDescription(busCode.getDescription());
			transVo.setTransName(new StringBuilder().append(transVo.getBizCode()).append("-").append(transVo.getDescription()).toString());
		}

		PeriodDomain period = transDo.getPeriod();
		if (!BlankUtil.isBlank(period)) {
			transVo.setPeriodId(period.getKeyword());
			transVo.setPeriod(period.getPeriod());
		}

		VoucherDomain voucher = transDo.getVoucher();
		if (!BlankUtil.isBlank(voucher)) {
			transVo.setVoucherId(voucher.getVoucherId());
			transVo.setVoucherNumber(voucher.getVoucherNumber());
			transVo.setChargeDate(voucher.getChargeDate());
		}

		SysInfo sysInfo = transDo.getSysInfo();//得到创建信息和修改信息
		if (!BlankUtil.isBlank(sysInfo)) {
			BeanUtil.convertVoAsDo(sysInfo, transVo);
		}
	}

	/**
	 * 功能描述: 装配一个AbstractTransVO，
	 * 判断参数transDo交易类型，使用应收交易VO或实收交易VO实例化 <br>
	 * @param transDo
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-1  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private AbstractTransVO assembleD2V(AbstractTrans transDo){
		AbstractTransVO transVo = null;

		if (!BlankUtil.isBlank(transDo)) {
			//判断交易类型，得到相应实例化VO对象
			transVo = this.dealDEOrCR(transDo);

			BeanUtil.convertVoAsDo(transDo, transVo);

			AbstractSubAccount subAccount = transDo.getBindingAccount();
			if (!BlankUtil.isBlank(subAccount)) {
				transVo.setSubAccountId(subAccount.getSubAccountId());
				transVo.setAccountId(subAccount.getAccount().getAccountId());
			}

			BusinessCodeDomain busCode = transDo.getBusinessCode();
			if (!BlankUtil.isBlank(busCode)) {
				transVo.setBusinessId(busCode.getKeyword());
				transVo.setBizCode(busCode.getBizCode());
				transVo.setDescription(busCode.getDescription());
			}
			PeriodDomain period = transDo.getPeriod();
			if (!BlankUtil.isBlank(period)) {
				transVo.setPeriodId(period.getKeyword());
				transVo.setPeriod(period.getPeriod());
			}

			SysInfo sysInfo = transDo.getSysInfo();//得到创建信息和修改信息
			if (!BlankUtil.isBlank(sysInfo)) {
				BeanUtil.convertVoAsDo(sysInfo, transVo);
			}
		}

		return transVo;
	}

	/**
	 * 功能描述: 装配一个CreditTransDomain实体 <br>
	 * @param creditTransVO 实收交易VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private CreditTransDomain assembleV2D(CreditTransVO creditTransVO){
		CreditTransDomain creditDo = (CreditTransDomain)this.wangleDomainInstance(creditTransVO);

		BeanUtil.convertVoAsDo(creditTransVO, creditDo);
		VoucherDomain voucher = this.chargeVoucherDao.loadById(creditTransVO.getVoucherId());
		creditDo.setVoucher(voucher);

		return creditDo;
	}

	/**
	 * 功能描述: 装配一个DebitTransDomain实体 <br>
	 * @param debitTransVO 应收交易VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private DebitTransDomain assembleV2D(DebitTransVO debitTransVO){
		DebitTransDomain debitDo = (DebitTransDomain)this.wangleDomainInstance(debitTransVO);

		BeanUtil.convertVoAsDo(debitTransVO, debitDo);

		//得到收费标准当前版本
		AbstractStaVersion curVersion = this.chargeStaDao.queryCVersionByChargeStaId(debitTransVO.getChargeStdId());
		debitDo.setStaVersion(curVersion);

		//得到来源产权房间
		HouseDomain house = this.houseService.getHouseById(debitTransVO.getHouseId());
		debitDo.setHouse(house);

		String remark = debitTransVO.getRemark()==null?"":debitTransVO.getRemark();
		remark = new StringBuilder(FROM_HOUSE_NUMBER).append(house.getHouseNumber()).append(";").append(remark).toString();
		if (TRANS_REMARK_LENGTH < remark.length()) {
			remark = remark.substring(0, TRANS_REMARK_LENGTH-1);
		}
		//在备注字段中加入房号，作为交易摘要
		debitDo.setRemark(remark);
		debitTransVO.setRemark(remark);
		//设置本金交易id
		debitDo.setMTransId(debitTransVO.getRootTransId());
		return debitDo;
	}


	/** 功能描述:  <br>
	 * @param subDebit
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-17  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private TransactionVO assemblevDebit2TransactionVO(DebitTransDomain subDebit) {
		TransactionVO tempTransvo = new TransactionVO();
		tempTransvo.setClazz(subDebit.getClazz());
		tempTransvo.setPrice(subDebit.getDebit());
		tempTransvo.setTransactionId(subDebit.getTransactionId());
		tempTransvo.setTransName(subDebit.getBusinessCode().getBizCode()
						+ "-"
						+ this.sysrefcodeDao.getSysrefCodesByCode(
										SysrefcodeDO.FEE_TRANSACTION_CLAZZ_CODE,
										subDebit.getClazz()).getName());
		tempTransvo.setPeriod(subDebit.getPeriod().getPeriod());
		tempTransvo.setHandTime(subDebit.getSysInfo().getSysDate());
		tempTransvo.setParentId(subDebit.getMTransId());
		return tempTransvo;
	}

	/**
	 * 功能描述: 在调用之前需要请初始化本类持有的Map:transStatusMap 和 transClazzMap <br>
	 * @param objArray
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-9  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private TransactionVO assemblevObjArray2TransactionVO(Object[] objArray) {
		TransactionVO transVo = new TransactionVO();

		if (!BlankUtil.isBlank(objArray)) {
			transVo.setTransactionId(objArray[0]==null?null:((BigInteger)objArray[0]).longValue());//交易id
			//[1]：子账户id SUB_ACCOUNT_ID
			transVo.setPrice(objArray[2]==null?BigDecimal.ZERO:(BigDecimal)objArray[2]);//交易金额
			transVo.setClazz(objArray[3]==null?null:(String)objArray[3]);//交易类型代码
			transVo.setClazzName(this.transClazzMap.get(transVo.getClazz()));//交易类型名称
			transVo.setStatuz(objArray[4]==null?null:(String)objArray[4]);//交易状态代码
			transVo.setStatuzName(this.transStatusMap.get(transVo.getStatuz()));//交易状态名称
			transVo.setHouseId(objArray[5]==null?null:((BigInteger)objArray[5]).longValue());//来源产权房id
			transVo.setChargeStandardVersionId(objArray[6]==null?null:((BigInteger)objArray[6]).longValue());//收费标准当前版本id
			transVo.setVoucherId(objArray[7]==null?null:((BigInteger)objArray[7]).longValue());//凭 证id
			transVo.setTransName(objArray[8]==null?null:(String)objArray[8]);//交易名称
			transVo.setPeriod(objArray[9]==null?null:(String)objArray[9]);//收费周期
			transVo.setRemark(objArray[10]==null?null:(String)objArray[10]);//交易摘要
			transVo.setHandTime(objArray[11]==null?null:(Date)objArray[11]);//记账日期
			//[12]：消费日期，INPUT_DATE
			Long operatId  = objArray[13]==null?null:((BigInteger)objArray[13]).longValue();
			transVo.setCreator(operatId);//操作人id
			if (SysrefcodeDO.FEE_TRANSACTION_CLAZZ_LATEFEES.equals(transVo.getClazz())) {
				transVo.setOperatorName(SysrefcodeDO.FEE_LATEFEES_TRANS_OPERATOR);//操作人名称
			}else{
				if (operatId != null) {
					// 操作人名称
					if (this.hmployeeNameCacheMap.get(operatId)==null) {
						this.hmployeeNameCacheMap.put(operatId, this.secUserService.queryUserNameById(operatId));
					}
					transVo.setOperatorName(this.hmployeeNameCacheMap.get(operatId));
				}
			}

			transVo.setParentId(objArray[14]==null?null:((BigInteger)objArray[14]).longValue());//所属主交易id
		}

		return transVo;
	}

	/** 功能描述: 计算调整金额 <br>
	 * @param debitVo
	 * @param adjustTransVo
	 * @param relationType
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 *
	*/
//	private void calculateAdjustPrice(DebitTransVO debitVo, AdjustTransactionVO adjustTransVo) {
//		this.calculatePrice(debitVo, adjustTransVo);
//	}

	/** 功能描述: 装配一个TransactionVO对象用于支付明细 <br>
	 * @param objects 对象数组
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-17  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private TransactionVO assemblevTransVOForPayDetail(Object[] objects) {
		TransactionVO transvo = new TransactionVO();
		String clazz = objects[6]==null?null:(String)objects[6];
		transvo.setClazz(clazz);//交易类型代码
		BigDecimal price = null;
		if (transvo.isDebitTransaction()) {
			price = objects[1]==null?BigDecimal.ZERO:(BigDecimal)objects[1];
		}else {
			price = objects[2]==null?BigDecimal.ZERO:(BigDecimal)objects[2];
		}
		transvo.setPrice(price);
		transvo.setTransactionId(objects[0]==null?null:((BigInteger)objects[0]).longValue());//交易id
		transvo.setTransName(objects[3]==null?null:(String)objects[3]);//交易名称
		transvo.setPeriod(objects[4]==null?null:(String)objects[4]);//收费周期
		transvo.setHandTime(objects[5]==null?null:(Date)objects[5]);//记账日期
		transvo.setParentId(objects[7]==null?null:((BigInteger)objects[7]).longValue());//主交易id
		return transvo;
	}

	/** 功能描述: 计算减免金额 <br>
	 * @param debitVo
	 * @param reliefTransVo
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-4  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 * @param relationType TODO
	*/
//	private void calculateReliefPrice(DebitTransVO debitVo, AdjustTransactionVO reliefTransVo) {
//		this.calculatePrice(debitVo, reliefTransVo);
//	}

	/**
	 * 功能描述: 计算指定交易的已调整金额和已减免金额和余额 <br>
	 * @param debitVo 应收交易
	 * @param adjustTransVo 调整交易
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-18  <br>
	 * Edit author: 付湘辉 <br>
	 * Edit on:  2008-10-10  <br>
	 * Why:  因调整和减免独立对原始本金进行，将造成数据混乱，
	 * 现改为在调整和减免都计算出已调整和减免的金额，
	 * 并使用原始本金的交易金额加上已调整和减免金额作为下次调整(减免)的基础   <br>
	 */
	private void calculatePrice(DebitTransVO debitVo, AdjustTransactionVO adjustTransVo) {
		List<BigDecimal> list = this.transactionDao.queryDebitSubTransDebitList(debitVo.getTransactionId(), SysrefcodeDO.FEE_TRA_R_TRA_RELATION_TYPE_ADJUSTMENT, true, null);
		BigDecimal haveAdjustPrice=BigDecimal.valueOf(000l, 2);
		for (BigDecimal decimal : list) {
			//计算已调整金额
			haveAdjustPrice = haveAdjustPrice.add(decimal,BigDecimalUtil.getMathContext());
		}

		list = this.transactionDao.queryDebitSubTransDebitList(debitVo.getTransactionId(), SysrefcodeDO.FEE_TRA_R_TRA_RELATION_TYPE_RELIEF, true, null);
		BigDecimal haveReliefPrice=BigDecimal.valueOf(000l, 2);
		for (BigDecimal decimal : list) {
			//计算已减免金额
			haveReliefPrice = haveReliefPrice.add(decimal,BigDecimalUtil.getMathContext());
		}
		//设置已调整金额
		adjustTransVo.setHaveAdjustPrice(haveAdjustPrice);
		//		设置已减免金额
		adjustTransVo.setHaveReliefPrice(haveReliefPrice.abs());

		//计算当前的交易金额
		BigDecimal curTransPrice=debitVo.getDebit().add(haveAdjustPrice,BigDecimalUtil.getMathContext()).add(haveReliefPrice,BigDecimalUtil.getMathContext());
		adjustTransVo.setCurTransPrice(curTransPrice);

		// 计算调整(减免)后金额
		adjustTransVo.setReliefBalance(curTransPrice);
	}

	/**
	 * 功能描述: 判断应收交易能否进行调整或减免,
	 * 只有应收本金或滞纳金在未缴状态时才能调整或减免 <br>
	 * @param status 状态
	 * @param clazz 类型
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-18  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	@SuppressWarnings("unused")
	@Deprecated
	private boolean canAdjustOrRilief(String status,String clazz){
		return (SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY.equals(status)
				&&(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_PRINCIPAL.equals(clazz)
				||SysrefcodeDO.FEE_TRANSACTION_CLAZZ_LATEFEES.equals(clazz)));
	}

	/**
	 * 功能描述:是否要找指定类型交易的父交易  <br>
	 * @param clazz
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-11  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private boolean canFindFather(String clazz){
		return SysrefcodeDO.FEE_TRANSACTION_CLAZZ_ADJUSTMENT.equals(clazz)
		||SysrefcodeDO.FEE_TRANSACTION_CLAZZ_LATEFEES.equals(clazz)
		||SysrefcodeDO.FEE_TRANSACTION_CLAZZ_RELIEF.equals(clazz);
	}

	/**
	 * 功能描述: 是否要找指定类型交易的子交易 <br>
	 * @param clazz
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-11  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private boolean canFindSon(String clazz){
		return SysrefcodeDO.FEE_TRANSACTION_CLAZZ_PRINCIPAL.equals(clazz)
		|| SysrefcodeDO.FEE_TRANSACTION_CLAZZ_LATEFEES.equals(clazz);
	}

	/**
	 * 功能描述:  <br>
	 * @param info
	 * @param modifier
	 * @param sysDate
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-12-3  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private void changeInfo(SysInfo info,Long modifier,Date sysDate) {
		info.setModifier(modifier);
		info.setModifyDate(sysDate);
	}

    /**
     * 功能描述: 改变指定应收交易及其子交易的状态，并返回子交易金额之和，
     * 如果某子交易的状态与oldStatus不符，则不进行更改，也不累计其金额 <br>
     * @param debitTrans 主交易
     * @param oldStatus 要修改的状态
     * @param status 新的状态
     * @param operator 操作人id
     * @param withLatefees 如果有滞纳金时，是否更改滞纳金的状态和累计其金额
     * @param sysDate TODO
     * @return 指定交易的所有子交易的借方金额和
     * Create author:付湘辉 <br>
     * Create on:2008-9-16  <br>
     * Edit author:  <br>
     * Edit on:    <br>
     * Why:     <br>
     */
    private BigDecimal changeTransStatus(DebitTransDomain debitTrans,final String oldStatus,final String status,Long operator, Boolean withLatefees, Date sysDate){
    	Set<TraRtra> set = debitTrans.getTraRtras();
    	BigDecimal total = BigDecimal.valueOf(000l,SysrefcodeDO.DATA_PRICE_SCALE);
    	for (TraRtra rtra : set) {
            AbstractTrans trans = rtra.getRelatingTrans();
            if (trans instanceof DebitTransDomain) {
                DebitTransDomain subDebitTrans = (DebitTransDomain)trans;
                if (oldStatus.equals(subDebitTrans.getStatuz())) {
                	if (SysrefcodeDO.FEE_TRANSACTION_CLAZZ_LATEFEES.equals(subDebitTrans.getClazz())) {
                		if (withLatefees) {
                			total = total.add(changeTransStatus(subDebitTrans,oldStatus,status,operator, withLatefees, sysDate),BigDecimalUtil.getMathContext());
                			total = total.add(subDebitTrans.getDebit(),BigDecimalUtil.getMathContext());
                		}
    				} else {
    					total = total.add(subDebitTrans.getDebit(),BigDecimalUtil.getMathContext());
	                	//设置应收交易的状态
	                    subDebitTrans.setStatuz(status);
	                    this.changeInfo(subDebitTrans.getSysInfo(), operator,sysDate);
    				}
                }
            }
        }
    	if (oldStatus.equals(debitTrans.getStatuz())) {
    		debitTrans.setStatuz(status);
        	this.changeInfo(debitTrans.getSysInfo(), operator,sysDate);
    	}
    	return total;
    }

	/**
	 * 功能描述:  检查一个交易是否能被调整或减免 <br>
	 * @param debitVo 将被调整或减免的交易
	 * @param adjustOrRilier 表示操作类型 1表示调整  2表示减免
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-11-13  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private void checkCanAdjustOrRilief(DebitTransVO debitVo,String adjustOrRilier){
		//如果是调整操作
		if (SysrefcodeDO.CONSTANTS_DIGITAL_ONE.equals(adjustOrRilier)) {
			// 不是未缴状态的本金交易不能调整
			if (!SysrefcodeDO.FEE_TRANSACTION_CLAZZ_PRINCIPAL.equals(debitVo.getClazz())
					|| !SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY.equals(debitVo.getStatuz())) {
				throw new BusinessException("charge:charge_not_notpayprincipal_donot_adjust_exception",
						BusinessException.WARNING);
			}
		} else if (SysrefcodeDO.CONSTANTS_DIGITAL_TWO.equals(adjustOrRilier)) {
			// 不是未缴状态的本金交易或滞纳金不能减免
			if (!(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_PRINCIPAL.equals(debitVo.getClazz())
					|| SysrefcodeDO.FEE_TRANSACTION_CLAZZ_LATEFEES.equals(debitVo.getClazz()))
					|| !SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY.equals(debitVo.getStatuz())) {
				throw new BusinessException("charge:charge_not_notpayprincipal_donot_relief_exception",
						BusinessException.WARNING);
			}
		}

	}

	/** 功能描述: 缴费时的检查，目前不能缴负数款 <br>
	 *
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-11-10  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void checkCreditForCharge(CreditTransVO creditVo) {
		checkCreditIsNull(creditVo);
		if (1 == BigDecimal.ZERO.compareTo(creditVo.getCredit())) {
			   throw new BusinessException("charge:charge_paycharge_not_negative_exception",
						BusinessException.WARNING);
	    }
	}

	/** 功能描述: 预交款，押金收款时的检查，收款金额不能为零。 <br>
	 *
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-11-10  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void checkCreditForPreDepCharge(CreditTransVO creditVo) {
		checkCreditIsNull(creditVo);
		if (0 == BigDecimal.ZERO.compareTo(creditVo.getCredit())) {
			   throw new BusinessException("charge:charge_prepay_not_equls_zero_exception",
						BusinessException.WARNING);
	    }
	}

	/** 功能描述:  <br>
	 * @param transVo
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private CreditTransVO checkCreditInstance(AbstractTransVO transVo) {
		CreditTransVO creditVo = null;
		if (transVo instanceof CreditTransVO) {
			creditVo = (CreditTransVO)transVo;
		}else {
			throw new BusinessException(
					"charge:charge_assign_trans_isnot_credit_exception",
					BusinessException.WARNING);
		}
		return creditVo;
	}

	/** 功能描述:  <br>
	 *
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-11-10  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void checkCreditIsNull(CreditTransVO creditVo) {
		if (BlankUtil.isBlank(creditVo.getCredit())) {
			   throw new BusinessException("common:mustFill_null_exception",
						BusinessException.WARNING);
	    }
	}

	/**
	 * 功能描述: 检查传入的日期对象所表示的时间
	 * 是否比当前数据库系统时间晚，如果晚则抛出异常 <br>
	 * @param inputDate
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 * @param now TODO
	 */
	private void checkInputDate(Date inputDate, Date now){
		if (!BlankUtil.isBlank(inputDate)) {
			boolean isAfterNow = inputDate.after(now);
			if (isAfterNow) {
				throw new BusinessException("charge:charge_inputdate_not_after_now_exception",
						BusinessException.WARNING);
			}
		}

	}

	/**
	 * 功能描述: 检查多重支付中每笔子支付交易是否设置了金额，
	 * 并且子支付交易之和与主交易金额是否相等 <br>
	 *
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-12  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private void checkMultiplePayPrice(CreditTransVO creditVo){
	   checkCreditForCharge(creditVo);
	   BigDecimal total = BigDecimalUtil.getZEROInstance();
	   if (!BlankUtil.isBlank(creditVo.getChildrens())) {
		   for (CreditTransVO cTransVo : creditVo.getChildrens()) {
			   if (BlankUtil.isBlank(cTransVo.getCredit())) {
				   throw new BusinessException("charge:charge_subpay_not_credit_price_exception",
						   		BusinessException.WARNING);
			   }
			   total = total.add(cTransVo.getCredit());
		   }

		   if (0 != creditVo.getCredit().compareTo(total)) {
			   throw new BusinessException("charge:charge_multiplepay_subsum_notequal_main_exception",
				   		BusinessException.WARNING);
		   }
	   }
	}

	/** 功能描述:建立押金抵冲关系  <br>
	 * @param depositTransVO
	 * @param debitTransVO
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-14  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void createDepositOffsetRelation(CreditTransVO creditTransVO,DepositTransVO depositTransVO) {
		// 查询出主支付交易实体
		AbstractTrans mainCreditTrans = this.transactionDao.findById(creditTransVO.getTransactionId());
		// 查询出主押金抵冲交易实体
		AbstractTrans mainDepositTrans = this.transactionDao.findById(depositTransVO.getTransactionId());
		//建立抵冲关系
		this.addOneTransactionRelation(mainCreditTrans,mainDepositTrans,SysrefcodeDO.FEE_TRA_R_TRA_RELATION_TYPE_DEPOSIT_TOUCH);
	}

	/**
	 * 功能描述: 根据实收交易VO生成一个收费凭证，
	 * 在参数creditTransVO中应该有总账id：accountId <br>
	 * @param creditTransVO 实收交易VO
	 * @param sysInfo TODO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private VoucherDomain createVoucher(CreditTransVO creditTransVO, SysInfo sysInfo){
		VoucherDomain voucher = new VoucherDomain();
		//凭证状态新建
		voucher.setStatuz(SysrefcodeDO.FEE_VOUCHER_STATUZ_NEW);
		Long accountId = creditTransVO.getAccountId();
		AccountDomain account = this.accountService.getAccountDoById(accountId);
		HouseDomain house = account.getHouse();
		voucher.setHouse(house);
		voucher.setProRight(account.getProRight());

		voucher.setSysInfo(sysInfo);
		if (BlankUtil.isBlank(creditTransVO.getChargeDate())) {
			voucher.setChargeDate(sysInfo.getSysDate());
		}else{
			this.checkInputDate(creditTransVO.getChargeDate(), sysInfo.getSysDate());
			voucher.setChargeDate(creditTransVO.getChargeDate());
		}
		//得到当天收费次数
		Integer curDayChargeTimes = this.chargeVoucherDao.getMaxVoucherNumSeqByType(creditTransVO.getVoucherNoPrefix());
		//生成凭证号码
		String voucherNumber = this.generationVoucherNumber(creditTransVO.getVoucherNoPrefix(),
							creditTransVO.getPrecinctCode(),
							voucher.getChargeDate(),
							curDayChargeTimes);
		voucher.setVoucherNumber(voucherNumber);
		creditTransVO.setVoucherNumber(voucherNumber);
		voucher.setSum(creditTransVO.getCredit().abs());
		voucher.setPrintTimes((short)0);

		this.chargeVoucherDao.saveObject(voucher);

		return voucher;
	}

	/** 功能描述: 处理收费子账户id <br>
	 * @param searchVo
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-3  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void dealChargeSubAccountId(ChargeDetailSearchVO searchVo) {
		if (BlankUtil.isBlank(searchVo.getSubAccountId())) {
			AccountDomain account = this.accountService.getAccountDoById(searchVo.getAccountId());
			Set<AbstractSubAccount> set = account.getSubAccounts();
			Long subAccountId = null;
			for (AbstractSubAccount subAccount : set) {
				if (subAccount instanceof ChargeAccountDomain) {
					subAccountId = subAccount.getSubAccountId();
					break;
				}
			}
			if (BlankUtil.isBlank(subAccountId)) {
				throw new BusinessException("charge:charge_not_subaccount_id_exception",
											BusinessException.WARNING);
			}
			searchVo.setSubAccountId(subAccountId);
		}
	}

	/**
     * 功能描述:   <br>
     *
     * @param creditTransVO
     * @param mainPayTrans
     *
     * Create author：付湘辉  <br>
     * Create on:2008-9-14  <br>
     * Edit author：  <br>
     * Edit on:    <br>
     * Why:     <br>
     */
    private void dealDebitAndCreditRelation(CreditTransVO creditTransVO, AbstractTrans mainPayTrans) {
        BigDecimal total = BigDecimalUtil.getZEROInstance();
        //得到应收集合
        Set<DebitTransVO> debits = creditTransVO.getDebits();
        //获取数据库时间
        Date sysDate = creditTransVO.getSysDate();
        if (!BlankUtil.isBlank(debits)) {
	        	for (DebitTransVO dtransVO : debits) {
				if (BlankUtil.isBlank(dtransVO.getTransactionId())) {
					continue;
				}
				//处理应收总和
	            dealDebitTransReceivalblePrice(dtransVO);
	            total=total.add(dtransVO.getReceivablePrice(),BigDecimalUtil.getMathContext());//计算应缴费用总和
	//         total=total.add(dtransVO.getDebit(),BigDecimalUtil.getMathContext());//计算应缴费用总和
				AbstractTrans dTrans = this.transactionDao.findById(dtransVO.getTransactionId());
	            DebitTransDomain debitTrans = (DebitTransDomain)dTrans;
	            //改变交易状态
	            this.changeTransStatus(debitTrans,
	            		SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY,
	            		SysrefcodeDO.FEE_TRANSACTION_STATUZ_PAYED,
	            		creditTransVO.getCreator(), true, sysDate);
	            /*debitTrans.setStatuz(SysrefcodeDO.FEE_TRANSACTION_STATUZ_PAYED);*/
	            //添加一笔支付关系
	            this.addOneTransactionRelation(mainPayTrans, dTrans,
	                    SysrefcodeDO.FEE_TRA_R_TRA_RELATION_TYPE_PAY);
			}
        }
		if (0 != total.compareTo(creditTransVO.getCredit())) {
			throw new BusinessException("charge:charge_pay_notequal_debit_sum_exception",
			   		BusinessException.WARNING);
		}
    }

	/**
     * 功能描述:  应收交易的实际应缴费用总和计算 <br>
     *
     * @param dtransVO
     *
     * Create author：付湘辉  <br>
     * Create on:2008-9-14  <br>
     * Edit author：  <br>
     * Edit on:    <br>
     * Why:     <br>
     */
    private void dealDebitTransReceivalblePrice(DebitTransVO dtransVO) {
        BigDecimal tempTotal = null;
        if (BlankUtil.isBlank(dtransVO.getReceivablePrice())) {
            List<BigDecimal> list
                = this.transactionDao.queryDebitSubTransDebitList(
                                        dtransVO.getTransactionId(),null, false,
                                        SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY);
            tempTotal = BigDecimalUtil.getZEROInstance();
            for (BigDecimal decimal : list) {
                tempTotal=tempTotal.add(decimal);
            }
            dtransVO.setReceivablePrice(dtransVO.getDebit().add(tempTotal));
        }
    }

	/** 功能描述: 判断参数transDo  <br>
	 * @param transDo
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-4  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private AbstractTransVO dealDEOrCR(AbstractTrans transDo) {
		AbstractTransVO transVo=null;
		DebitTransDomain debit=null;
		CreditTransDomain credit=null;
		if (transDo instanceof DebitTransDomain) {
			transVo = new DebitTransVO();
			DebitTransVO debitvo = (DebitTransVO)transVo;
			debit = (DebitTransDomain)transDo;

			AbstractStaVersion version = debit.getStaVersion();
			if (!BlankUtil.isBlank(version)) {
				debitvo.setChargeStdVertionId(version.getStaHisId());
			}
			HouseDomain house = debit.getHouse();
			if (!BlankUtil.isBlank(house)) {
				debitvo.setHouseId(house.getKeyword());
				debitvo.setRootTransId(debit.getMTransId());
			}
		}else if(transDo instanceof CreditTransDomain){
			transVo = new CreditTransVO();
			credit = (CreditTransDomain)transDo;
			CreditTransVO creditvo = (CreditTransVO)transVo;
			VoucherDomain voucher = credit.getVoucher();
			if (!BlankUtil.isBlank(voucher)) {
				creditvo.setVoucherId(voucher.getVoucherId());
				creditvo.setVoucherNumber(voucher.getVoucherNumber());
				creditvo.setChargeDate(voucher.getChargeDate());
			}
		}
		return transVo;
	}

	/** 功能描述: 在备注字段中加入衍生交易的交易摘要说明 <br>
	 * @param adjustTransVO
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-18  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void dealDerivativeTransRemark(AdjustTransactionVO adjustTransVO) {
		//得到输入的摘要
		StringBuffer remark = new StringBuffer();
		//拼接交易摘要
		remark.append(adjustTransVO.getPeriod())
			  .append(TRANS_REMARK_PERIOD)
			  .append(adjustTransVO.getTransName())
			  .append(adjustTransVO.getRemark()==null?"":SysrefcodeDO.CONSTANTS_SEMICOLON+adjustTransVO.getRemark());
		adjustTransVO.setRemark(remark.toString());
	}

	/** 功能描述: 处理滞纳金支付明细 <br>
	 * @param creditVo
	 * @param transvo
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-18  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void dealLatefeePayDetail(CreditTransVO creditVo, TransactionVO transvo) {
		AbstractTrans latefeeTrans = this.transactionDao.findById(transvo.getTransactionId());
		Set<TraRtra> set = latefeeTrans.getTraRtras();
		for (TraRtra rtra : set) {
			AbstractTrans subtrans = rtra.getRelatingTrans();
			if (subtrans instanceof DebitTransDomain) {
				DebitTransDomain subDebit = (DebitTransDomain)subtrans;
				if (!SysrefcodeDO.FEE_TRANSACTION_STATUZ_PAYED.equals(subDebit.getStatuz())) {
					continue;
				}
				TransactionVO tempTransvo = assemblevDebit2TransactionVO(subDebit);
				creditVo.getDebitsList().add(tempTransvo);
			}
		}
	}

	/**
     * 功能描述:  处理多重支付时主支付与子支付关系 <br>
     *
     * @param sets
     * @param mainPayTrans
     *
     * Create author：付湘辉  <br>
     * Create on:2008-9-14  <br>
     * Edit author：  <br>
     * Edit on:    <br>
     * Why:     <br>
     */
    private void dealMainPayAndSubForMultiple(Set<CreditTransVO> sets, AbstractTrans mainPayTrans) {
    	if (!BlankUtil.isBlank(sets)) {
	        for (CreditTransVO ctransVO : sets) {
				AbstractTrans cTrans = this.transactionDao.findById(ctransVO.getTransactionId());
				if (BlankUtil.isBlank(cTrans)) {
					continue;
				}
	            this.addOneTransactionRelation(mainPayTrans, cTrans,
	                    SysrefcodeDO.FEE_TRA_R_TRA_RELATION_TYPE_MULTIPLEPAY);
			}
    	}
    }

	/**
	 * 功能描述: 处理一个主支付交易的交易关系，包括应收支付关系和多重支付 <br>
	 * @param creditVo
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-16  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private void dealPayTransDetail(CreditTransVO creditVo){
		List<Object[]> tempList = this.transactionDao.queryPayDetailList(creditVo.getTransactionId());
		creditVo.setDebitsList(new ArrayList<TransactionVO>());
		creditVo.setChildrenList(new ArrayList<TransactionVO>());
		for (Object[] objects : tempList) {
			TransactionVO transvo = this.assemblevTransVOForPayDetail(objects);
			if (transvo.isDebitTransaction()) {

				if (SysrefcodeDO.FEE_TRANSACTION_CLAZZ_LATEFEES.equals(transvo.getClazz())) {
					this.dealLatefeePayDetail(creditVo, transvo);
				}

				creditVo.getDebitsList().add(transvo);
			}else {
				creditVo.getChildrenList().add(transvo);
			}
		}
		Collections.sort(creditVo.getDebitsList(), PmsUtilityComparator.getComparator());
		Collections.sort(creditVo.getChildrenList(), PmsUtilityComparator.getComparator());
	}

	/**
     * 功能描述:  处理一笔主支付交易的子支付交易(如果是多重支付生效) <br>
     *
     * @param creditTransVO
     * @return
     *
     * Create author：付湘辉  <br>
     * Create on:2008-9-14  <br>
     * Edit author：  <br>
     * Edit on:    <br>
     * Why:     <br>
     */
    private Set<CreditTransVO> dealSubPayTrans(CreditTransVO creditTransVO) {
        Set<CreditTransVO> sets = creditTransVO.getChildrens();
        if (!BlankUtil.isBlank(sets)) {
        	for (CreditTransVO ctransVO : sets) {
    			ctransVO.setSubAccountId(creditTransVO.getSubAccountId());
    			ctransVO.setPeriodId(creditTransVO.getPeriodId());
    			ctransVO.setVoucherId(creditTransVO.getVoucherId());
    			ctransVO.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_SUBSIDIARYPAY);
    			ctransVO.setCreator(creditTransVO.getCreator());
                //增加一笔子支付交易
    			this.addSubsidiaryPayCreditTransAction(ctransVO);
    		}
    	}
        return sets;
    }

	/**
	 * 功能描述: 处理不同类型交易的共同属性值 <br>
	 * @param abstractTrans
	 * @param abstractTransVO
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private void dealTransactionPropertie(AbstractTrans abstractTrans,AbstractTransVO abstractTransVO){
		//得到收费周期
		PeriodDomain period = this.periodService.getPeriodDomainById(abstractTransVO.getPeriodId());
		abstractTrans.setPeriod(period);
		//得到交易码
		BusinessCodeDomain businessCode = this.businessCodeDao.loadById(abstractTransVO.getBusinessId());
		abstractTrans.setBusinessCode(businessCode);
		//得到绑定子帐户
		AbstractSubAccount subAccount = this.subAccountDao.loadById(abstractTransVO.getSubAccountId());
		abstractTrans.setBindingAccount(subAccount);
	}

	/** 功能描述: 处理一笔交易关系 <br>
	 * @param adjustTransVO
	 * @param relationType
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void dealTransactionRelation(AbstractTransVO masterTransVo,AbstractTransVO reliefTransVo,String relationType) {
		//得到主交易
		AbstractTrans masterTrans = this.transactionDao
									.findById(masterTransVo.getTransactionId());
		//得到关联交易
		AbstractTrans reliefTrans = this.transactionDao
									.findById(reliefTransVo.getTransactionId());
		//添加一笔交易关系表记录，并按指定关系类型添加
		this.addOneTransactionRelation(masterTrans, reliefTrans,relationType);
        this.transactionDao.updateObject(masterTrans);
	}

	private void destoreAllMapCache(){
		this.destoreHmployeeCache();
		this.destoreTransClazzCache();
		this.destoreTransStatusCache();
	}

	private void destoreHmployeeCache(){
		this.hmployeeNameCacheMap = null;
	}

	private void destoreTransClazzCache(){
		this.transClazzMap = null;
	}

	private void destoreTransStatusCache(){
		this.transStatusMap = null;
	}

	/**
	 * 功能描述: 生成一个新的收费凭证号码，格式如下： <br>
	 * <ul>
	 * <li>
	 * prefix + "-" + 管理区编码 + "-" + 收费日期 + "-" + 五位顺序号(如：00001)
	 * 示例：1管理区 2008年8月8号第二次收费凭证号码： JFT-1-20080808-00002
	 * </li>
	 * </ul>
	 * @param prefix 号码前缀
	 * @param precinctCode 管理区编码
	 * @param chargeDate 收费日期
	 * @param curDayTimes 当天已收费次数
	 * @exception com.ce.pms.exception.BusinessException
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private String generationVoucherNumber(String prefix,String precinctCode,Date chargeDate,Integer curDayTimes){
		if (BlankUtil.isBlank(precinctCode)) {
			throw new BusinessException("charge:charge_precinctcode_isnull_exception",
							BusinessException.WARNING);
		}

		final String speator = "-";
		NumberFormat nf = NumberFormat.getInstance();
		nf.setMinimumIntegerDigits(5);
		nf.setMaximumFractionDigits(0);
		nf.setGroupingUsed(false);
		nf.setParseIntegerOnly(true);

		StringBuffer sb = new StringBuffer();
		sb.append(prefix).append(speator);
		sb.append(precinctCode).append(speator);
		if (BlankUtil.isBlank(chargeDate)) {
			chargeDate = super.getDate();
		}
		String dateStr = DateUtil.convertDateToStr(chargeDate, DateUtil.DATE_COMPACT_FORMAT);
		sb.append(dateStr).append(speator);
		String times = nf.format(++curDayTimes);
		sb.append(times);
		return sb.toString();
	}

	/**
	 * 功能描述: 根据传入id查询一个交易 <br>
	 * @param transId
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-9  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private AbstractTransVO getAbstractTransVOById(Long transId){
		super.checkParameterIsNull(transId, "common:parameters_null_exception,ID");

		AbstractTrans tractTrans = this.transactionDao.findById(transId);
		AbstractTransVO transVo = this.assembleD2V(tractTrans);

		return transVo;
	}

	/***
	 * 功能描述:  获取滞纳金公式<br>
	 * @param baseMoney
	 * @param days
	 * @param rate
	 * @return
	 * Create author:yandawei <br>
	 * Create on:2008-9-26  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private String getCalculateLateFeeFormula(BigDecimal baseMoney,Long days,BigDecimal rate,BigDecimal
			result){
		StringBuffer sb = new StringBuffer();
		sb.append("(").append(baseMoney).append("×").append(rate).append("%)").append("×").append(days).append("=").append(result);
		return sb.toString();
	}

	/**
	 * 功能描述: 查询交易表(FEE_TRANSACTION)当天收费次数 <br>
	 * @param clazz 交易类型
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author: 付湘辉 <br>
	 * Edit on:2008-12-30    <br>
	 * Why: 为统一调用，在收费凭证Dao已有相同功能实现    <br>
	 */
	@SuppressWarnings("unused")
	@Deprecated
	private Integer getCurDayChargeTimes(String clazz){
		if (BlankUtil.isBlank(clazz)) {
			throw new BusinessException("charge:charge_transaction_clazz_null_exception",
										BusinessException.WARNING);
		}
		Integer count = this.transactionDao.getCurDayChargeTimes(clazz);

		return count;
	}

	/** 功能描述: 得到一个应收交易VO <br>
	 * @param transVo
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private DebitTransVO getDebitInstance(AbstractTransVO transVo) {
		DebitTransVO debitVo = null;
		if (transVo instanceof DebitTransVO) {
			debitVo = (DebitTransVO)transVo;
		}else {
			throw new BusinessException(
					"charge:charge_assign_trans_isnot_debit_exception",
					BusinessException.WARNING);
		}
		return debitVo;
	}

	/***
	 * 功能描述:  比较两个时间相差多少天<br>
	 * @param beginDate
	 * @param endDate
	 * @return
	 * Create author:yandawei <br>
	 * Create on:2008-9-26  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	@SuppressWarnings("unused")
	@Deprecated
	private Long getMargin(Date beginDate , Date endDate){
		long dayCount = 0l;
        dayCount = (endDate.getTime() - beginDate.getTime())/ (24 * 60 * 60 * 1000);
        return dayCount;
	}

	/** 功能描述: 查询费用明细VO列表 <br>
	 * @param searchVo 搜索VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-11  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private  List<TransactionVO> getTransactionVoList(ChargeDetailSearchVO searchVo) {
		List<Object[]> list = this.transactionDao.queryTransactionBy(searchVo);
		List<TransactionVO> tempList=null;
		synchronized (this) {
			initMapCache();
			final int size = list.size();
			int i = 0;
			tempList = new ArrayList<TransactionVO>();
			for (i = 0; i < size; i++) {
				Object[] objArray = list.get(i);
				TransactionVO transVo = this
						.assemblevObjArray2TransactionVO(objArray);
				tempList.add(transVo);
			}
			this.destoreAllMapCache();
		}
		return tempList;
	}

	/** 功能描述:  <br>
	 * @param operator
	 * @param accountHouseId
	 * @param debitTransVO
	 * @param creditTransVO
	 * @param account
	 * @param chargeAccount
	 * @param periodVo
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-14  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private Boolean handleOneChargeInner(Long operator, Long accountHouseId, DebitTransVO debitTransVO, CreditTransVO creditTransVO, AccountDomain account, ChargeAccountDomain chargeAccount, PeriodVO periodVo) {
		debitTransVO.setSubAccountId(chargeAccount.getSubAccountId());
		debitTransVO.setPeriodId(periodVo.getKeyword());
		debitTransVO.setPeriod(periodVo.getPeriod());
		debitTransVO.setCreator(operator);
		//入账
		debitTransVO = this.addPrincipalTransaction(debitTransVO);
		debitTransVO.setReceivablePrice(debitTransVO.getDebit());

		// 填充实收交易VO
		creditTransVO.setAccountId(account.getAccountId());
		creditTransVO.setSubAccountId(chargeAccount.getSubAccountId());
		creditTransVO.setPeriodId(periodVo.getKeyword());
		creditTransVO.setCredit(debitTransVO.getDebit());
		creditTransVO.setCreator(operator);
		Set<DebitTransVO> debitTransVOs = new HashSet<DebitTransVO>();
		debitTransVOs.add(debitTransVO);
		creditTransVO.setDebits(debitTransVOs);
		//缴费处理：增加一笔实收交易
		creditTransVO = this.addChargeTransaction(creditTransVO);
		return true;
	}

	private void initHmployeeNameCache(){
		this.hmployeeNameCacheMap = new HashMap<Long, String>();
	}

	/**
	 * 功能描述: 根据本金交易id查询本金交易并初始化调整或者减免VO <br>
	 * @param transId 本金交易id
	 * @param adjustOrRilier 表示操作类型 1表示调整  2表示减免
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-18  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private AdjustTransactionVO initializeAdjustTransByMasterId(Long transId,String adjustOrRilier){
		AbstractTransVO transVo = this.getAbstractTransVOById(transId);
		DebitTransVO debitVo = getDebitInstance(transVo);
		//判断是否可以减免或调整
		this.checkCanAdjustOrRilief(debitVo, adjustOrRilier);

		AdjustTransactionVO adjustTransVo = new AdjustTransactionVO();
		this.initializePartField(debitVo, adjustTransVo);

		//计算金额
		this.calculatePrice(debitVo, adjustTransVo);

		return adjustTransVo;
	}

	/** 功能描述: 初始化部分字段 <br>
	 * @param debitVo
	 * @param adjustTransVo
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-7  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void initializePartField(DebitTransVO debitVo, AdjustTransactionVO adjustTransVo) {
		adjustTransVo.setBusinessId(debitVo.getBusinessId());
		adjustTransVo.setBizCode(debitVo.getBizCode());
		adjustTransVo.setHouseId(debitVo.getHouseId());
		adjustTransVo.setSubAccountId(debitVo.getSubAccountId());
		adjustTransVo.setPeriodId(debitVo.getPeriodId());
		adjustTransVo.setPeriod(debitVo.getPeriod());
		adjustTransVo.setChargeStdVertionId(debitVo.getChargeStdVertionId());
		adjustTransVo.setStatuz(debitVo.getStatuz());
		//主交易id
		if (SysrefcodeDO.FEE_TRANSACTION_CLAZZ_LATEFEES.equals(debitVo.getClazz())){
			adjustTransVo.setRootTransId(debitVo.getRootTransId());
		}else{
			adjustTransVo.setRootTransId(debitVo.getTransactionId());
		}

		// 交易名称
		adjustTransVo.setTransName(debitVo.getBizCode()+"-"+debitVo.getDescription());
		//设置本金交易VO
		adjustTransVo.setPrincipalTrans(debitVo);
	}

	/**
	 * 功能描述: 初始化临时数据 <br>
	 *
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-11-27  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private void initMapCache(){
		this.initTransClazzMap();
		this.initTransStatusMap();
		this.initHmployeeNameCache();
	}

	private void initTransClazzMap(){
		this.transClazzMap = new HashMap<String, String>();
		List<SysrefcodeDO> list = this.sysrefcodeDao.querySysrefCodesByCode(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_CODE);
		   for (Iterator<SysrefcodeDO> iter = list.iterator(); iter.hasNext();) {
			   SysrefcodeDO element = iter.next();
			   this.transClazzMap.put(
									   element.getValue(),
									   element.getName());
		   }
	}

	private void initTransStatusMap(){
		this.transStatusMap = new HashMap<String, String>();
		List<SysrefcodeDO> list = this.sysrefcodeDao.querySysrefCodesByCode(SysrefcodeDO.FEE_TRANSACTION_STATUZ);
	    for (Iterator<SysrefcodeDO> iter = list.iterator(); iter.hasNext();) {
		    SysrefcodeDO element = iter.next();
		    this.transStatusMap.put(
								   element.getValue(),
								   element.getName());
	    }
	    //如果是支付交易，业务上都用 - 表示状态
		transStatusMap.put("-","-");
	}

	/**
	 * 功能描述: 先判断id是否存在，
	 *  如果不存在，返回一个new AbstractTrans，否则，从系统中加载一个实体<br>
	 * @param abstractTransVO 交易VO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-29  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private AbstractTrans wangleDomainInstance(AbstractTransVO abstractTransVO){
		AbstractTrans abstractTrans = null;

		if (!BlankUtil.isBlank(abstractTransVO)) {
			SysInfo sysInfo = null;
			if (BlankUtil.isBlank(abstractTransVO.getTransactionId())) {
				//判断是不是应收交易
				if (abstractTransVO.isDebitTransaction()) {
					abstractTrans = new DebitTransDomain();
				}else{
					abstractTrans = new CreditTransDomain();
				}

//				sysInfo = super.createInfo(abstractTransVO.getCreator());
//				if (!BlankUtil.isBlank(abstractTransVO.getSysDate())) {
//					sysInfo.setSysDate(abstractTransVO.getSysDate());
//				}
//				abstractTrans.setSysInfo(sysInfo);
//				abstractTransVO.setSysDate(sysInfo.getSysDate());
			}else{
				abstractTrans = this.transactionDao.findById(abstractTransVO.getTransactionId());
				sysInfo = abstractTrans.getSysInfo();
				super.modifyInfo(sysInfo, abstractTransVO.getModifier());
				abstractTransVO.setModifyDate(sysInfo.getModifyDate());
			}
		}

		this.dealTransactionPropertie(abstractTrans, abstractTransVO);

		return abstractTrans;
	}

}
